单靠 list 无法实现 O(1) 获取最小值,因 min() 是 O(n),且 pop 后无法快速获知剩余最小值;需用辅助栈或元组记录历史最小值,并严格同步维护。

为什么单靠 list 实现不了 O(1) 获取最小值
Python 的 list 作为栈用(append/pop)时,min() 是 O(n),每次调用都要遍历;缓存一个 self._min 变量看似可行,但 pop 后无法快速知道“剩下的最小值”——除非你重新扫一遍,那就又退化成 O(n)。
用辅助栈同步维护最小值
核心思路:用另一个栈 self._min_stack,和主栈严格同步——每次 push(x) 时,把当前全局最小值(即 min(x, self._min_stack[-1]))压入辅助栈;pop() 时两个栈一起弹出。这样 get_min() 只需返回 self._min_stack[-1],稳稳 O(1)。
注意点:
- 辅助栈初始要压入一个极大值(如
float('inf')),避免首次比较出错 -
push时不能只在x <= 当前最小才压入——否则pop多次相同最小值时,辅助栈会提前空掉 - 必须严格同步:哪怕
x比当前最小值大,也要把当前最小值再压一次(保证栈高一致)
示例关键片段:
立即学习“Python免费学习笔记(深入)”;
def push(self, x):
self._stack.append(x)
current_min = self._min_stack[-1]
self._min_stack.append(min(x, current_min))
用 tuple 存最小值更省内存
如果不想多维护一个栈,可以把最小值直接打包进元素本身:self._stack.append((x, min(x, self._stack[-1][1] if self._stack else float('inf'))))。这样每个元素是 (value, min_so_far),get_min() 直接取栈顶元组的第二个字段。
优点:省一个栈对象,逻辑更集中;缺点:每个元素多存一个值,空间略增,且初始化判空稍啰嗦。
常见误写:
- 写成
min(x, self._stack[-1][1])却没处理空栈——触发IndexError: list index out of range - 把
min_so_far算成min(x, 当前全局最小)而非min(x, 上一个 min_so_far),导致历史最小信息丢失
实际使用中容易漏掉的边界
所有实现都必须显式处理空栈调用 get_min() 或 pop() 的情况,否则抛 IndexError 或 ValueError。别指望用户永远记得先 is_empty()。
建议统一策略:
-
get_min()在空栈时返回None或抛ValueError("empty stack"),不要静默返回错误值 -
pop()和top()同理,不建议返回哨兵值(比如 -1),容易掩盖逻辑 bug - 如果业务场景确定不会空栈访问,至少加
assert self._stack,比裸奔强
最麻烦的其实是测试:得覆盖重复最小值、递减序列、先增后减、空栈访问这些 case,少一个就可能线上崩。


















