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