跳到正文
第 155 题中等

最小栈

Min Stack

设计一个栈,支持 push、pop、top 和 O(1) 的 getMin。

在力扣中练习

题目描述

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

实现 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
  • pop、top 和 getMin 操作总是在 非空栈 上调用
  • push, pop, top, and getMin最多被调用 3 * 104 次

解题思路

主解法

主栈 + 辅助最小值栈

辅助栈顶始终保存当前最小值

只用主栈无法 O(1) 取最小值;每次遍历一遍是 O(n)。用一个辅助栈 mins 记录“到这个位置为止的最小值”即可。

push 时,如果新值不大于当前最小值,就同时压入 mins。用 <= 而不是 <,是为了处理重复最小值:弹出其中一个时,另一个仍然保留在 mins 里。

分步图解

主栈保存所有元素,辅助栈保存“到这个位置为止的最小值”;两个栈同步维护。

data · 主栈后进先出
从栈顶进入与离开
    空栈
    栈底
    mins · 每个位置对应的最小值后进先出
    从栈顶进入与离开
      空栈
      栈底
      操作
      push(5)push(2)push(6)getMinpoppush(1)getMinpoptop
      1 / 4
      mins 只在更小或相等时入栈,因此栈顶始终是当前最小值。

      pop 时,如果主栈弹出的值正好等于 mins 栈顶,mins 也弹出一个;否则 mins 不变。

      分步图解

      pop():弹出 6;它不是最小值,mins 不变。

      data · 主栈后进先出
      6↑ 出栈
      1. 5
      2. 2← top
      栈底
      mins · 每个位置对应的最小值后进先出
      从栈顶进入与离开
      1. 5
      2. 2← top
      栈底
      操作
      push(5)push(2)push(6)getMinpoppush(1)getMinpoptop
      1 / 4
      弹出当前最小值后,辅助栈同步回退,新的栈顶就是之前的最小值。

      自拟操作里,6 比当前最小值 2 大,所以不进入 mins;1 进入后,getMin 返回 1;pop 掉 1 后,mins 栈顶回到 2。所有操作 O(1),额外空间 O(n)。

      时间 O(1)空间 O(n)

      易错点

      • push 用 < 而不是 <=:重复的最小值只存一份,弹出一个后 getMin 就错了。
      • pop 只弹主栈:mins 没有同步回退。
      • 用变量保存当前最小值:最小值被弹出后无法恢复次小值。

      代码与演示

      演示输入push(5), push(2), push(6), getMin(), pop(), push(1), getMin(), pop(), top()

      主栈保存所有元素,辅助栈保存“到这个位置为止的最小值”;两个栈同步维护。

      data · 主栈后进先出
      从栈顶进入与离开
        空栈
        栈底
        mins · 每个位置对应的最小值后进先出
        从栈顶进入与离开
          空栈
          栈底
          操作
          push(5)push(2)push(6)getMinpoppush(1)getMinpoptop
          1 / 11
          查看 C++ 代码

          延伸阅读

          • “每个位置对应的最小值”本质上是一个前缀最小值数组,用栈只是让它随 push/pop 同步伸缩。
          • 同理可以维护前缀最大值、前缀和等可合并信息。