0x01.问题
设计一个支持 push
,pop
,top
操作,并能在常数时间内检索到最小元素的栈。
push(x)
—— 将元素 x 推入栈中。pop()
—— 删除栈顶的元素。top()
—— 获取栈顶元素。getMin()
—— 检索栈中的最小元素。
示例:
输入: [“MinStack”,“push”,“push”,“push”,“getMin”,“pop”,“top”,“getMin”]
[[],[-2],[0],[-3],[],[],[],[]]输出: [null,null,null,null,-3,null,0,-2]
解释:
MinStack minStack = new MinStack();
minStack.push(-2);
minStack.push(0);
minStack.push(-3);
minStack.getMin(); --> 返回 -3.
minStack.pop();
minStack.top();
–> 返回 0. minStack.getMin();
–> 返回 -2.
提示:
pop
、top
和getMin
操作总是在 非空栈 上调用。
0x02.详细算法思路
-
我们发现这个最小栈最重要的特征就是 在常数级的时间得到最小值。(这也是这个算法核心)
-
仔细思考一下,如何才能在常数级别的时间获取最小值?
-
既然是常数级别的时间,那么这个最小值肯定在其它操作时已经生成了,到具体某一个栈顶元素,只要拿来用就行。
-
初始的时候,会想到维护一个全局的最小值,根据相应的操作更新就行了。但是,这里就存在一个问题,栈是会不断更新的,如何当前的最小值已经
pop
了,那么,如何去寻找下一个最小值,所以,单一的维护一个最小值,肯定是不行的。 -
既然单一的维护不行,这暗示着我们,需要去维护一个数组级别最小值,这个数组级别应该满足什么特征呢?
- 需要满足,对于每个栈顶元素,都能找到对应的最小值。
-
也就是说,我们维护的这个数组级别的最小值需要和栈的每个元素相对应,最好的解决办法是什么?
- 没错,就是维护一个辅助栈,对于原栈的每个栈顶元素,辅助栈中对应的元素就是其最小值。
-
-
具体辅助栈的维护思路:
- 初始时,辅助栈中放入一个元素
Integer.MAX_VALUE
。目的是避免非空判断。 - 每次进行
push(x)
操作时,对辅助栈的操作是F.push(min{x,F.peek()})
。也就是放入x
和当前栈顶中的最小值,这个维护步骤就是保持两栈始终对应的关键步骤。 - 每次进行
pop()
操作时,两栈同时pop()
。 - 每次进行
getMin()
操作时,返回F.peek()
。
- 初始时,辅助栈中放入一个元素
0x03.解决代码–辅助栈的维护
class MinStack {
private Stack<Integer> S=new Stack<>();
private Stack<Integer> F=new Stack<>();
/** initialize your data structure here. */
public MinStack() {
F.push(Integer.MAX_VALUE);
}
public void push(int x) {
F.push(Math.min(F.peek(),x));
S.push(x);
}
public void pop() {
F.pop();
S.pop();
}
public int top() {
return S.peek();
}
public int getMin() {
return F.peek();
}
}
ATFWUS --Writing By 2020–05-12