最小栈--辅助最小值栈的维护

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

你可能感兴趣的:(算法,算法,栈,最小栈,栈维护,辅助栈)