最小棧--輔助最小值棧的維護

0x01.問題

設計一個支持 pushpoptop 操作,並能在常數時間內檢索到最小元素的棧。

  • 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.

提示:

  • poptopgetMin 操作總是在 非空棧 上調用。

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章