单用一个栈无法o(1)取最小值,因栈仅支持栈顶操作且无遍历接口,遍历求最小值为o(n);需用空间换时间,如双栈法(主栈+同步最小栈)或单栈存差值法。

为什么单用一个栈无法做到O(1)取最小值
因为栈只允许在栈顶操作,std::stack 本身不提供遍历或查找最小值的接口。每次调用 getMin() 如果临时遍历栈内元素,时间复杂度就是 O(n),违背要求。
核心思路是:用空间换时间,额外维护一个“同步最小值栈”,让它的栈顶始终等于主栈当前状态下的最小值。
双栈法:主栈 + 辅助最小栈(最常用且易理解)
辅助栈 minStack 和主栈 dataStack 同步压入、同步弹出,但只在满足条件时才向 minStack 压入:
- 压入新元素
x时,若minStack为空,或x ,则也压入 <code>minStack - 弹出时,若
dataStack.top() == minStack.top(),则同步弹出minStack -
getMin()直接返回minStack.top(),O(1)
注意等号 很关键——否则遇到重复最小值(如连续压入 3, 1, 1)时,第二次 1 不进 <code>minStack,弹出第一个 1 后 minStack 就空了,导致错误。
单栈法:栈中存差值(节省空间但易错)
只用一个栈,但每个元素不直接存原始值,而是存它与「历史最小值」的差值。同时用一个变量 minVal 记录当前全局最小值。
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
关键逻辑:
- 压入
x:若栈空,设minVal = x,压入 0;否则压入x - minVal;若该差值 x 更小,更新minVal = x - 弹出:若栈顶 ≤ 0,说明当时更新过
minVal,需还原旧的minVal(即minVal = minVal - 栈顶值) -
getMin()直接返回minVal
这个方法省空间,但整数溢出风险高(比如 minVal 是 INT_MIN,再减一个负差值就溢出),调试困难,实际工程中极少采用。
使用 std::stack 实现时的典型陷阱
最容易被忽略的是边界处理和类型一致性:
- 栈为空时调用
top()或getMin()是未定义行为——必须在getMin()、pop()前检查empty() - 如果用
std::stack<int></int>,别忘了所有比较和运算都基于int,不要混用long long或无符号类型 - 辅助栈法里,两个栈的
size()不一定相等(这是正常现象),不能靠 size 判断是否该弹辅助栈 - 构造函数里记得初始化
minStack为空,别误写成默认构造后又手动 push 一个极大值(比如INT_MAX),这会污染第一次getMin()
真正难的不是写出代码,而是在多轮 push/pop 交错、含重复最小值、栈空边缘情况下,每一步的栈状态都符合预期——建议手画三组数据走一遍流程再敲代码。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










