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; } }