最小栈、最大栈、双向支持的最小最大栈
✅ 什么是最小栈(Min Stack)?
最小栈是一种支持常数时间内(O(1)) 获取栈中最小值的栈结构。
🔧 标准栈的限制
通常,使用普通栈只能O(n) 时间遍历才能找出最小值:
1 | stack = [3, 4, 2, 5] |
但最小栈支持:
push(x)
:压入元素pop()
:移出栈顶top()
:查看栈顶元素getMin()
:O(1) 获取栈中最小值
🧠 核心思想
借助一个辅助栈来同步维护当前栈的最小值。例如:
操作 | 原始栈(main_stack) | 最小栈(min_stack) |
---|---|---|
push(5) | 5 | 5 |
push(3) | 5, 3 | 5, 3 |
push(4) | 5, 3, 4 | 5, 3, 3 |
pop() | 5, 3 | 5, 3 |
getMin() | return 3 |
top of min_stack |
✅ Python 最小栈实现示例
1 | class MinStack: |
🧰 操作说明
push(val)
:将val
压入主栈;同时,将新最小值压入min_stack
pop()
:主栈和最小栈同时弹出getMin()
:直接返回min_stack
栈顶
🧮 时间复杂度
操作 | 时间复杂度 |
---|---|
push() |
O(1) |
pop() |
O(1) |
top() |
O(1) |
getMin() |
O(1) |
🚀 更加节省空间的变体(不重复最小元素)
上面的方法中 min_stack
与主栈等长,因为每次都同步 push,但你也可以只在 min
发生变化时记录保存:
1 | class MinStack: |
🔸这种写法更节省空间,适用于要求内存优势的场合。
📌 典型应用场景
- 实现含最小值查询功能的数据结构
- 辅助解决滑动窗口、括号匹配、区间最小值等问题
- LeetCode 原题:155. 最小栈
✅ 总结
特性 | 说明 |
---|---|
支持操作 | push、pop、top、getMin |
时间复杂度 | 所有操作均为 O(1) |
核心数据结构 | 主栈 + 最小栈 |
空间优化方法 | 只在 val <= 当前最小 时记录 |
当然可以!下面我们讨论一种扩展数据结构:同时支持 O(1) 查询最小值和最大值的栈,即: |
✅ 双向支持的最小最大栈(MinMax Stack)
💡 需求描述
构建一个MinMax 栈,支持以下操作,且所有操作都为 O(1) 时间复杂度:
push(val)
:将元素压入栈pop()
:移除栈顶top()
:返回栈顶元素getMin()
:返回当前栈中最小值getMax()
:返回当前栈中最大值
✅ 思路
除了维护主栈,我们再用两个辅助栈:
min_stack
:记录每一状态下的最小值max_stack
:记录每一状态下的最大值
每次压栈时,同步更新 min_stack
和 max_stack
。
🧠 图解(push 操作)
假设我们依次压入:[3, 2, 5, 1]
Main Stack | Min Stack | Max Stack |
---|---|---|
3 | 3 | 3 |
2 | 2 ← min(2,3) | 3 ← max(2,3) |
5 | 2 | 5 |
1 | 1 ← min(1,2) | 5 |
✅ Python 实现
1 | class MinMaxStack: |
✅ 示例用法
1 | s = MinMaxStack() |
📊 时间 & 空间复杂度
方法 | 时间复杂度 | 空间复杂度(辅助栈) |
---|---|---|
push | O(1) | O(n) |
pop | O(1) | O(1) |
top | O(1) | O(1) |
getMin | O(1) | O(1) |
getMax | O(1) | O(1) |
✅ 空间优化(可选)
你可以进一步优化空间:只在新值小于等于当前 min / max 时才入栈
但这样做的话 pop()
时需要判断当前值是否是 min / max
,略微增加复杂度。
例如:
1 | if not min_stack or val <= min_stack[-1]: |
🔁 拓展
- 如果你还希望
getMin
和getMax
支持在 队列中 实现(单调队列),则涉及:- 单调栈 / 单调队列
- 滑动窗口(滑窗最大最小)
- 可参考:LeetCode 239 滑动窗口最大值
✅ 总结
结构 | 支持操作 | getMin / getMax | 时间复杂度 | 空间复杂度 |
---|---|---|---|---|
正常栈 | push, pop, top | ✗ | O(1) | O(n) |
最小栈 | push, pop, top, getMin | ✓(min only) | O(1) | O(n) |
最大栈 | push, pop, top, getMax | ✓(max only) | O(1) | O(n) |
MinMax栈 | push, pop, top, getMin, getMax | ✓(both) | O(1) | O(n) |
这种结构在许多算法面试中是高频考点。灵活掌握它将对你解决各类 “最值 + 动态结构” 类问题非常有帮助。需要我给出相关题目练习吗?
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Min的博客!
评论