Problem Description 设计一个支持 push ,pop ,top 操作,并能在常数时间内检索到最小元素的栈。
push(x) —— 将元素 x 推入栈中。
pop() —— 删除栈顶的元素。
top() —— 获取栈顶元素。
getMin() —— 检索栈中的最小元素。
e.g. 1 2 3 4 5 6 7 8 1. MinStack minStack = new MinStack ();2. minStack.push(-2 );3. minStack.push(0 );4. minStack.push(-3 );5. minStack.getMin(); ==> 返回 -3. 6. minStack.pop();7. minStack.top(); ==> 返回 0. 8. minStack.getMin(); ==>返回 -2.
Solution 该题很简单,但是有意思的是,我的解法也算通过了,虽然题目说
在常数时间内检索到最小元素的栈。
但是这里应该指的是getMin()
这个方法,所以即使我的push(Object obj)
方法复杂度比较高也没关系。。
因为有删除元素(pop方法)的存在,所以最小值在push完之后还是会随时变。所以单纯使用一个变量来保存最小值是不可能的。
我使用了双栈来实现,实际不用双栈用其他的数据结构也可以。大概原理就是在push的过程中,一个标准stack正常push,另一个辅助栈从栈底到栈顶从小到大排序的插入,利用了Stack的父类(Vector)方法insertElementAt(Object obj, int i)
,这里注意index是第二个参数。pop时,标准stack正常pop,辅助stack只需要remove标准stack刚刚pop返回的对象即可minStack.remove(stack.pop());
。这样确保两栈移除的元素是相同的。
代码如下: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 public class MinStack { private Stack<Integer> stack; private Stack<Integer> minStack; public MinStack () { stack = new Stack <>(); minStack = new Stack <>(); } public void push (int x) { stack.push(x); if (minStack.empty()) { minStack.push(x); } else if (x >= minStack.peek()) { minStack.push(x); } else { for (int i = 0 ; i <= minStack.size(); i++) { if (x < minStack.get(i)) { minStack.insertElementAt(x, i); break ; } } } } public void pop () { minStack.remove(stack.pop()); } public int top () { return stack.peek(); } public int getMin () { return minStack.firstElement(); } @Override public String toString () { return "MinStack{" + "stack=" + stack + ", minStack=" + minStack + '}' ; } public static void main (String[] args) { MinStack minStack = new MinStack (); minStack.push(-2 ); minStack.push(0 ); minStack.push(-3 ); minStack.push(-11 ); minStack.push(-1 ); System.out.println(minStack.toString()); System.out.println(minStack.getMin()); minStack.pop(); minStack.top(); System.out.println(minStack.getMin()); } }
Feature 虽然我这样做是通过的,但其实我想的不够多,看了高赞的题解,即使是利用辅助栈push方法时间复杂度也可以不到线性级 O (n )。
因为题目是说了设计的该栈对于移除元素只有pop方法,就是从栈顶移除,也就是说next元素比当前顶部元素大的话,就没必要保留了,因为在只有pop方法的情况下,该元素一定是先被移除的。所以在条件下辅助栈可以不需要把所有元素保存。
除非题目加一个删除中间某个元素的方法的条件。
当然还有不用辅助栈的做法,利用压栈。