题目描述
定义栈的数据结构,请在该类型中实现一个能够得到栈最小元素的min函数。在该栈中,调用min、push以及pop的时间复杂度都是O(1)。
思路:
第一种思路,可不可以每次push操作后,对栈中元素排序,使最小的元素位于栈顶?这样min操作可以保证在O(1)内完成,但pop操作就与栈的pop操作违背了(栈顶的元素不一定是最后进栈的,不是后进先出)。显然这种思路行不通,直接pass掉。
第二种思路,可不可以用一个临时值保存min?如果最小元素pop出栈了,如何求当前栈中的min(原来的次最小元素)。顺着这种思路,是否可以使用数组来保存最小元素、次最小元素、…,可行,但比较复杂,因为数组对于增删维护不太方便(比如,你用数组下标来标识,0存放最小,那如果pop或push改变了栈中最小元素,都要移动数组元素,虽然找到minO(1),但维护O(n))。最终你会发现,用辅助栈来存放最小元素,满足题意要求。举个例子:向空的数据栈中压入3,此时栈中最小元素就是3,把3同时压入辅助栈。然后压入4,4>3,此时最小元素3,把3压入辅助栈。然后再压入2,2<3,此时最小元素2,把2压入辅助栈。再压入1,1<2,此时最小元素1,把1压入辅助栈。绘制如下表格:
步骤 | 操作 | 数据栈 | 辅助栈 | 最小值 |
---|---|---|---|---|
1 | 压入3 | 3 | 3 | 3 |
2 | 压入4 | 3,4 | 3,3 | 3 |
3 | 压入2 | 3,4,2 | 3,3,2 | 2 |
4 | 压入1 | 3,4,2,1 | 3,3,2,1 | 1 |
5 | 弹出 | 3,4,2 | 3,3,2 | 2 |
6 | 弹出 | 3,4 | 3,3 | 3 |
7 | 压入0 | 3,4,0 | 3,3,0 | 0 |
总结出方法:数据栈push元素时,与栈中最小元素比较(minStack.top()),并将比较后的最小元素push进辅助栈。当数据栈pop元素时,辅助栈也pop元素,更新最小元素。
写出代码:
import java.util.Stack;
public class Solution {
public static Stack<Integer> dataStack=new Stack<Integer>();
public static Stack<Integer> minStack=new Stack<Integer>();
public static void push(int node) {
dataStack.push(node);
if(dataStack.size()==0||node<top()){
minStack.push(node);
}
else{
minStack.push(top());
}
}
public static void pop() {
if(dataStack.size()>0&&minStack.size()>0){
dataStack.pop();
minStack.pop();
}
}
public static int top() {
if(minStack.size()>0){
return minStack.peek();
}
if(dataStack.size()>0){
return dataStack.peek();
}
return -1;
}
public static int min() {
return top();
}
public static void main(String[] args){
push(3);
push(4);
push(2);
push(1);
System.out.println(min());
pop();
System.out.println(min());
}
}