最小栈
约 623 字大约 2 分钟
2025-02-24
155. 最小栈
设计一个支持 push
,pop
,top
操作,并能在常数时间内检索到最小元素的栈。
实现 MinStack
类:
MinStack()
初始化堆栈对象。void push(int val)
将元素val推入堆栈。void pop()
删除堆栈顶部的元素。int top()
获取堆栈顶部的元素。int getMin()
获取堆栈中的最小元素。
示例 1:
输入:
["MinStack","push","push","push","getMin","pop","top","getMin"]
[[],[-2],[0],[-3],[],[],[],[]]
输出:
[null,null,null,null,-3,null,0,-2]
解释:
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^31 <= val <= 2^31 - 1
pop
、top
和getMin
操作总是在 非空栈 上调用push
,pop
,top
, andgetMin
最多被调用3 * 10^4
次
辅助栈-与数据栈同步
使用一个辅助栈,与元素栈同步插入与删除,删除都是删除栈顶元素,但插入的值不一样。 辅助栈中存储目前的最小值,这样每个元素 a
与其相应的最小值 m
时刻保持一一对应。
class MinStack {
// 主栈,用于存储所有元素
Deque<Integer> xStack;
// 辅助栈,栈顶元素为当前栈的最小元素
Deque<Integer> minStack;
public MinStack() {
// 初始化两个栈
xStack = new LinkedList<Integer>();
minStack = new LinkedList<Integer>();
// 为了简化操作,先在 minStack 中添加一个最大值。重点。
minStack.push(Integer.MAX_VALUE);
}
public void push(int x) {
// push 时先在 xStack 中添加元素。再在最小栈中添加当前最小值
xStack.push(x);
// 在 minStack 中添加当前最小值,通过比较 minStack 的栈顶元素(当前最小值)和新加入的元素 x 得到。重点。
minStack.push(Math.min(minStack.peek(), x));
}
public void pop() {
// 同时弹出 xStack 和 minStack 的栈顶元素
// 这保持了两个栈的同步,即 minStack 的栈顶总是对应 xStack 所有元素的最小值
xStack.pop();
minStack.pop();
}
public int top() {
// 获取 xStack 的栈顶元素,即最后一个加入的元素
return xStack.peek();
}
public int getMin() {
// 获取 minStack 的栈顶元素,即当前所有元素的最小值
return minStack.peek();
}
}
- 时间复杂度:对于题目中的所有操作,时间复杂度均为 O(1) 。因为栈的插入、删除与读取操作都是 O(1) ,我们定义的每个操作最多调用栈操作两次。
- 空间复杂度: O(n) ,其中 n 为总操作数。最坏情况下,我们会连续插入 n 个元素,此时两个栈占用的空间为 O(n) 。