在问 · 算法题解

155. 最小栈

中等栈与堆辅助最小值栈力扣原题 ↗

题目描述

设计一个栈类 MinStack。它支持常规的入栈、出栈和查看栈顶,还要能在常数时间内给出栈中的最小值。

需要实现的方法: - MinStack():创建一个空栈。 - void push(int val):把 val 放到栈顶。 - void pop():移除栈顶元素。 - int top():返回栈顶元素。 - int getMin():返回栈中当前的最小元素。

每个操作都应在 O(1) 时间内完成。

示例 1
输入:操作 = ["MinStack","push","push","push","getMin","pop","top","getMin"]
参数 = [[],[-2],[0],[-3],[],[],[],[]]
输出:[null,null,null,null,-3,null,0,-2]

解释:依次压入 -2、0、-3 后最小值是 -3;弹出 -3 后栈顶为 0,最小值变回 -2。

数据范围

  • -2^31 <= val <= 2^31 - 1
  • 调用 pop、top、getMin 时栈一定非空。
  • push、pop、top、getMin 合计最多调用 3 * 10^4 次。

解题思路:辅助最小值栈

主栈同步维护最小值栈。

为什么正确

辅助栈顶是当前最小值。

复杂度分析

每个操作的时间为 O(1),额外空间 O(n)。

易错点

注意边界条件并在回溯或弹出后恢复状态。

参考代码

Python、Java、C++、Go、JavaScript、TypeScript 六种语言,逻辑一致。

class MinStack:
 def __init__(self):self.s=[];self.m=[]
 def push(self,x):self.s.append(x);self.m.append(x if not self.m else min(x,self.m[-1]))
 def pop(self):self.s.pop();self.m.pop()
 def top(self):return self.s[-1]
 def getMin(self):return self.m[-1]

载入编辑器,自己跑一遍 →

其他解法

两种方法每个操作都是 O(1);辅助栈直观且不怕溢出,差值栈把最小值信息编码进差值里,省去第二个栈。

解法 2:差值栈 时间 O(1),空间 O(n)

只用一个栈和一个变量 mn 保存当前最小值。入栈时压入 x - mn,若差值为负说明 x 成为新最小值,令 mn = x。出栈时若栈顶差值为负,说明弹出的是当前最小值,用 mn - diff 恢复上一个最小值。取栈顶时,差值为负返回 mn,否则返回 mn + diff。

省掉辅助栈,只多一个变量。差值可能超出 32 位整数范围,C++/Java 需要用 64 位整数存储,代码也更难读。

class MinStack:
    def __init__(self):
        self.s = []
        self.mn = 0

    def push(self, x):
        if not self.s:
            self.s.append(0)
            self.mn = x
        else:
            d = x - self.mn
            self.s.append(d)
            if d < 0:
                self.mn = x

    def pop(self):
        d = self.s.pop()
        if d < 0:
            self.mn -= d

    def top(self):
        d = self.s[-1]
        return self.mn if d < 0 else self.mn + d

    def getMin(self):
        return self.mn

栈与堆 专题的其他题目

查看 栈与堆 全部题目 →