前面讲到了如何用数组以及链表实现一个基本的堆栈和队列,这篇文章介绍如何实现一个可以在O(1)时间复杂度下得到最小元素的堆栈,以及用堆栈实现一个队列,用队列实现一个堆栈。
1,实现一个可以得到最小元素的堆栈, 要求pop(),push(),getMin()的时间复杂度都为O(1).
如果我们按照普通的思路,类中有两个成员变量,value和minValue,当pop一个元素后,我们就需要更新minValue, 从而要遍历堆栈里剩余的元素,时间复杂度为O(n),假设堆栈中有n个元素,因此这个方法不符合题意。
我们想到用每个元素都记录当前的最小元素,当push一个新的元素进来,这个新的元素连同最小元素都被记录在堆栈中,我们先不考虑pop,实现代码如下:
public class StackWithMin extends Stack<EleWithMin>{
public void push(int val) {
int min = Math.min(val, min());
super.push(new EleWithMin(val, min));
}
public int pop() {
/*
after we pop a element,
how can we update the min in
stack if this is the minimum value
*/
super.pop().value;
}
public int min(){
if(this.isEmpty()){
return Integer.MAX_VALUE;
} else {
return peek().min;
}
}
}
class EleWithMin {
public int value;
public int min;
public EleWithMin(int value, int min) {
this.value = value;
this.min = min;
}
}
他的确可以在O(1)的时间内得到最小元素,但是pop后,我们仍然需要更新最小值,时间复杂度大于O(n)。并且浪费空间,因为每个元素都要记录一个当前的最小元素。我们换另一种方法,用另外一个堆栈来记录最小元素。代码如下:
import java.util.Stack;
public class StackWithMin extends Stack<Integer> {
Stack<Integer> minStack;
public StackWithMin() {
minStack = new Stack<Integer>();
}
public void push(int val) {
super.push(val);
if(minStack.isEmpty() || minStack.peek() >= getMin()){
minStack.push(val);
}
}
public Integer pop(){
int value = super.pop();
if(value == getMin()){
minStack.pop();
}
return value;
}
public int getMin() {
if(minStack.isEmpty()) {
return Integer.MAX_VALUE;
} else {
return minStack.peek();
}
}
}
2,用队列实现一个堆栈
借用两个队列,实现堆栈后进先出的原理。代码如下:
import java.util.LinkedList;
import java.util.Queue;
public class MyStack {
Queue<Integer> q1 = new LinkedList<Integer>();
Queue<Integer> q2 = new LinkedList<Integer>();
public void push(int val) {
q1.offer(val);
}
public int pop() {
while(q1.size() > 1) q2.offer(q1.poll());
int result = q1.poll();
Queue<Integer> q = q1;
q1 = q2;
q2 = q1;
return result;
}
public int peek() {
while(q1.size() > 1) q2.offer(q1.poll());
int result = q1.poll();
q2.offer(result);
Queue<Integer> q = q1;
q1 = q2;
q2 = q;
return result;
}
public boolean isEmpty() {
if(q1.size() == 0) {
return true;
} else {
return false;
}
}
}
3,用堆栈实现队列
思路和上一题类似,这里用两个堆栈来实现队列先进先出的原理。代码如下:
import java.util.Stack;
public class MyQueue {
Stack<Integer> stack1 = new Stack<Integer>();
Stack<Integer> stack2 = new Stack<Integer>();
public void offer(int val) {
stack1.push(val);
}
public int element() {
while(!stack1.isEmpty())
stack2.push(stack1.pop());
int result = stack2.pop(); //删除第一个元素
while(!stack2.isEmpty())
stack1.push(stack2.pop());
return result;
}
public int peek() {
while(!stack1.isEmpty())
stack2.push(stack1.pop());
int result = stack2.peek(); //不删除第一个的元素
while(!stack2.isEmpty())
stack1.push(stack2.pop());
return result;
}
public boolean empty() {
if(stack1.isEmpty())
return true;
return false;
}
}