单用一个栈无法o(1)获取最小值,因其仅支持栈顶操作,而最小值可能位于任意位置;需用辅助栈同步记录“截至当前的最小值”,push时x≤minstack.top()才入栈,pop时主栈弹出值等于minstack栈顶则同步弹出。

为什么单用一个栈没法 O(1) 拿到最小值
因为栈只允许在栈顶增删,而最小值可能藏在任意一层。如果每次 getMin() 都遍历一遍,就是 O(n),不满足题干要求。
核心思路是:用空间换时间,额外维护一个“同步栈”,它和主栈一起压入/弹出,但只存“到当前位置为止的最小值”。
- 主栈进
5,当前全局最小是5→ 辅助栈也进5 - 主栈再进
3,比辅助栈顶5小 → 辅助栈进3 - 主栈再进
4,不比辅助栈顶3小 → 辅助栈不动(或进3,两种实现都行) -
getMin()直接返回辅助栈顶,O(1)
push() 时辅助栈怎么更新才不出错
关键在判断逻辑:辅助栈只在新元素 ≤ 当前最小值时才压入。用 而不是 <code>,否则重复最小值会被漏掉,导致 <code>pop() 后 getMin() 返回错误值。
比如连续压入 3, 1, 1, 4,如果辅助栈只在 时进栈,第二个 <code>1 就不会进,等第一个 1 弹出后,辅助栈空了,但实际最小值还是 1。
立即学习“C++免费学习笔记(深入)”;
实操建议:
- 初始化两个空
std::stack<int></int>:主栈mainStack和辅助栈minStack -
push(x)时:先压mainStack,再判断minStack.empty() || x ,成立则压 <code>minStack - 别忘了处理空栈边界——
getMin()前必须检查minStack.empty(),否则.top()未定义行为
pop() 时辅助栈要不要跟着弹
要,而且必须严格同步:只要 mainStack 弹出的值等于 minStack.top(),minStack 就必须跟着弹一个。
不能只看“是不是当前最小”,而要看“它是不是当时被记下来的那个最小”。否则会残留过期最小值。
常见错误现象:push(2), push(1), push(1), pop(), getMin() 返回 1 是对的;但如果 pop() 时没检查相等就跳过辅助栈,第二次 getMin() 可能仍返回 1(其实是错的,应仍为 1?等等——这里恰恰说明:重复值必须都记,也必须都弹)
所以正确逻辑是:
-
pop()先取mainStack.top(),然后mainStack.pop() - 再比较这个值是否等于
minStack.top(),相等则minStack.pop() - 不相等就不管辅助栈
C++ 实现里最容易崩的三个点
不是算法难,是 C++ 栈操作细节容易踩雷:
-
std::stack::top()对空栈调用是未定义行为,不是抛异常——程序可能当场崩溃或静默错乱,务必每次调用前用.empty()检查 - 不要用
std::stack的底层容器(如std::vector)直接访问,它没暴露operator[]或迭代器;想调试时看内容,得临时转成 vector 或用while (!s.empty()) { auto t = s.top(); s.pop(); ... } - 如果题目要求支持
getMin()在空栈时返回特殊值(如INT_MAX),别直接 return,先判空;否则线上环境可能触发 sanitizer 报告
复杂点不在结构,而在每一步的边界守卫。少一个 empty() 检查,就可能让整个类在特定输入下失效。










