原题
栈与队列中等2 种解法

#155最小栈

实现支持 push、pop、top 和 O(1) getMin 的栈。

#设计#

原题

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

实现 MinStack 类:

  • MinStack() 初始化堆栈对象。
  • void push(int value) 将元素 value 推入堆栈。
  • 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.

提示:

  • -231 <= val <= 231 - 1
  • poptopgetMin 操作总是在 非空栈 上调用
  • pushpoptop, and getMin最多被调用 3 * 104 次

查看原题

解题主线

  1. 每个元素同时保存入栈后对应的最小值,弹栈时最小值自然回退。
  2. 双栈法让最小值栈与数据栈严格同步,每层都保存当前最小值。

解法 1:值与当前最小值成对入栈

每个栈帧保存 [value, minSoFar],所有操作只访问栈顶。

  • 时间复杂度: 所有操作 O(1)

  • 空间复杂度: O(n)

JAVA
import java.util.ArrayDeque;
import java.util.Deque;

final class MinStack {
    private final Deque<int[]> stack = new ArrayDeque<>();

    public void push(int value) {
        // 每个栈帧保存入栈后的最小值,使历史最小值随弹栈自然恢复。
        int minimum = stack.isEmpty() ? value : Math.min(value, stack.peek()[1]);
        stack.push(new int[] {value, minimum});
    }

    public void pop() {
        stack.pop();
    }

    public int top() {
        return stack.element()[0];
    }

    public int getMin() {
        // 栈顶第二个字段始终对应当前整个栈的最小值。
        return stack.element()[1];
    }
}

解法 2:数据栈 + 最小值栈

每次 push 都在辅助栈压入新的当前最小值,pop 时两栈同步弹出。

  • 时间复杂度: 所有操作 O(1)

  • 空间复杂度: O(n)

JAVA
import java.util.ArrayDeque;
import java.util.Deque;

final class MinStack {
    private final Deque<Integer> values = new ArrayDeque<>();
    private final Deque<Integer> minimums = new ArrayDeque<>();

    public void push(int value) {
        values.push(value);
        // 最小值栈逐层保存对应数据栈状态下的最小值,包括重复最小值。
        minimums.push(minimums.isEmpty() ? value : Math.min(value, minimums.peek()));
    }

    public void pop() {
        // 两个栈必须同步弹出,才能恢复到同一历史层级。
        values.pop();
        minimums.pop();
    }

    public int top() {
        return values.element();
    }

    public int getMin() {
        return minimums.element();
    }
}

实现提示

  • 补上旧双栈实现遗漏的 minimums.pop()。

边界与易错点

  • 旧双栈版 pop 只弹数据栈而未弹 minStack,导致最小值永久残留。
  • 重复最小值也必须逐层保存或计数,否则弹出一个后会错误丢失最小值。
  • ArrayDeque 不允许 null;题目保证只在非空栈调用查询操作。

整理来源

由旧仓库源码复核、去重并整理;展示代码已按 Java 21 语义修正明显问题。

  • medium/Q155_MinStack.java