LeetCode 155. 最小栈:Java 双栈解法详解
文章目录
- 1. 问题描述
- 2. 核心要求
- 3. 实现思路
- 双栈同步法
- 4. 完整代码实现
- 5. 复杂度分析
- 6. 总结与优化方向
- 方法优势
- 优化方向
- 适用场景
1. 问题描述
设计一个支持 push
、pop
、top
操作,并能在 常数时间 内检索到最小元素的栈。要求所有操作的时间复杂度均为 O(1)。
示例输入输出:
MinStack minStack = new MinStack();
minStack.push(-2);
minStack.push(0);
minStack.push(-3);
minStack.getMin(); // 返回 -3
minStack.pop();
minStack.top(); // 返回 0
minStack.getMin(); // 返回 -2
2. 核心要求
- 功能要求:实现栈的基本操作,并高效获取最小值。
- 时间复杂度:所有操作(
push
,pop
,top
,getMin
)必须为 O(1)。 - 空间复杂度:尽可能优化,但允许使用额外空间。
3. 实现思路
双栈同步法
通过维护两个栈实现功能:
- 主栈 (stack):存储所有元素。
- 辅助栈 (minStack):存储每个主栈状态下的最小值,与主栈同步操作。
关键操作:
- 入栈 (push):主栈压入元素,辅助栈压入当前最小值。
- 出栈 (pop):主栈和辅助栈同步弹出栈顶元素。
- 最小值查询 (getMin):直接访问辅助栈顶元素。
同步原理:
每次入栈时,辅助栈记录当前主栈的最小值;出栈时,辅助栈同步弹出元素,确保其栈顶始终是主栈当前的最小值。
4. 完整代码实现
import java.util.Deque;
import java.util.LinkedList;class MinStack {private Deque<Integer> stack; // 主栈:存储所有元素private Deque<Integer> minStack; // 辅助栈:存储每个状态的最小值public MinStack() {stack = new LinkedList<>();minStack = new LinkedList<>();}public void push(int val) {stack.push(val);// 辅助栈压入当前最小值:若栈为空,当前值为最小;否则与栈顶比较if (minStack.isEmpty()) {minStack.push(val);} else {minStack.push(Math.min(minStack.peek(), val));}}public void pop() {stack.pop();minStack.pop(); // 同步弹出辅助栈顶元素}public int top() {return stack.peek(); // 返回主栈顶元素}public int getMin() {return minStack.peek(); // 返回辅助栈顶元素(当前最小值)}
}
5. 复杂度分析
- 时间复杂度:所有操作均为 O(1),直接访问栈顶元素。
- 空间复杂度:O(n),其中 n 为操作次数。辅助栈与主栈大小相同,最坏情况下存储所有元素的最小值。
6. 总结与优化方向
方法优势
- 直观易懂:双栈同步操作逻辑清晰,代码简洁。
- 严格满足时间复杂度要求:所有操作均在常数时间内完成。
优化方向
- 空间优化:辅助栈可以不存储所有状态的最小值,而是当新值 ≤ 当前最小值时才压入辅助栈。弹出时,仅当主栈顶等于辅助栈顶时才弹出辅助栈顶。
示例:
优点:减少辅助栈空间占用。public void push(int val) {stack.push(val);if (minStack.isEmpty() || val <= minStack.peek()) {minStack.push(val);} }public void pop() {if (stack.pop().equals(minStack.peek())) {minStack.pop();} }
缺点:代码复杂度稍高,需处理对象相等性问题(如使用Integer
时需用equals
比较)。
适用场景
- 对时间复杂度要求严格,且可接受额外空间的场景。
- 需要快速获取最小值的栈结构设计问题。