Skip to content

最小栈

约 623 字大约 2 分钟

2025-02-24

155. 最小栈

设计一个支持 pushpoptop 操作,并能在常数时间内检索到最小元素的栈。

实现 MinStack 类:

  • MinStack() 初始化堆栈对象。
  • void push(int val) 将元素val推入堆栈。
  • void pop() 删除堆栈顶部的元素。
  • int top() 获取堆栈顶部的元素。
  • int getMin() 获取堆栈中的最小元素。

示例 1:

输入:
["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.

提示:

  • -2^31 <= val <= 2^31 - 1
  • poptopgetMin 操作总是在 非空栈 上调用
  • push, pop, top, and getMin最多被调用 3 * 10^4

辅助栈-与数据栈同步

使用一个辅助栈,与元素栈同步插入与删除,删除都是删除栈顶元素,但插入的值不一样。 辅助栈中存储目前的最小值,这样每个元素 a 与其相应的最小值 m 时刻保持一一对应。

155_fig1.gif

class MinStack {
    // 主栈,用于存储所有元素
    Deque<Integer> xStack;
    // 辅助栈,栈顶元素为当前栈的最小元素
    Deque<Integer> minStack;

    public MinStack() {
        // 初始化两个栈
        xStack = new LinkedList<Integer>();
        minStack = new LinkedList<Integer>();
        // 为了简化操作,先在 minStack 中添加一个最大值。重点。
        minStack.push(Integer.MAX_VALUE);
    }
    
    public void push(int x) {
        // push 时先在 xStack 中添加元素。再在最小栈中添加当前最小值
        xStack.push(x);
        // 在 minStack 中添加当前最小值,通过比较 minStack 的栈顶元素(当前最小值)和新加入的元素 x 得到。重点。
        minStack.push(Math.min(minStack.peek(), x));
    }
    
    public void pop() {
        // 同时弹出 xStack 和 minStack 的栈顶元素
        // 这保持了两个栈的同步,即 minStack 的栈顶总是对应 xStack 所有元素的最小值
        xStack.pop();
        minStack.pop();
    }
    
    public int top() {
        // 获取 xStack 的栈顶元素,即最后一个加入的元素
        return xStack.peek();
    }
    
    public int getMin() {
        // 获取 minStack 的栈顶元素,即当前所有元素的最小值
        return minStack.peek();
    }
}
  • 时间复杂度:对于题目中的所有操作,时间复杂度均为 O(1)O(1) 。因为栈的插入、删除与读取操作都是 O(1)O(1) ,我们定义的每个操作最多调用栈操作两次。
  • 空间复杂度: O(n)O(n) ,其中 nn 为总操作数。最坏情况下,我们会连续插入 nn 个元素,此时两个栈占用的空间为 O(n)O(n)