一、题目描述
设计一个支持 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.
提示:
-231 <= val <= 231 - 1
pop
、top
和getMin
操作总是在 非空栈 上调用push
,pop
,top
, andgetMin
最多被调用3 * 104
次
二、思路分析
由于需要在常数时间内找到最小的元素,那么说明肯定是不能使用遍历,因为遍历是 O(n) 级别的时间,那么只能使用辅助空间进行存储,即空间换时间。
这道题我们创建两个栈空间,一个是普通栈,一个是用来装最小值的辅助栈;
1、push 操作
普通栈:直接添加 push 进来的值
辅助栈:每次 push 一个新元素的时候,将普通栈中最小的元素 push 进辅助栈中
2、pop 操作
普通栈:直接移除普通栈中的栈顶元素
辅助栈:判断普通栈中刚刚移除的栈顶元素值是否和此时辅助栈中的栈顶元素相同,如果是则将辅助栈中的栈顶元素移除,否则不执行操作,这样的目的是为了让辅助栈中的栈顶元素始终是普通栈中的最小值。
3、top 操作
普通栈:返回普通栈的栈顶元素
辅助栈:不执行操作
4、getMin 操作
普通栈:不执行操作
辅助栈:返回辅助栈的栈顶元素
三、代码参考
1、Java
class MinStack {
// 首先定义好两个栈
// 一个栈叫做 stack,负责栈的正常操作
Stack<Integer> stack;
// 一个栈叫做 minStack,负责获取 stack 中的最小值,它等价于遍历 stack 中的所有元素,把升序的数字都删除掉,留下一个从栈底到栈顶降序的栈
Stack<Integer> minStack;
public MinStack() {
// 初始化 stack
stack = new Stack<>();
// 初始化 minStack
minStack = new Stack<>();
}
public void push(int val) {
// 新添加的元素添加到 stack 中
stack.push(val);
// 判断 minStack 是否为空,如果为空,直接同时把新添加的元素添加到 minStack 中
// 如果 minStack 不为空,则比较
if (!minStack.isEmpty()) {
// 获取 minStack 的栈顶元素
int top = minStack.peek();
// 只有新添加的元素不大于 top 才允许添加到 minStack 中,目的是为了让 minStack 从栈底到栈顶是降序的
if (val <= top) {
// 此时,新添加的元素 x 小于 top,加入到 minStack 后依旧是从栈底到栈顶是降序的
minStack.push(val);
}
}else{
// 此时,minStack 中没有元素,所以直接把新添加的元素添加到 minStack 中
minStack.push(val);
}
}
public void pop() {
// 让 stack 执行正常的 pop 操作就行
int pop = stack.pop();
// 由于 minStack 中的所有元素都是来自于 stack 中,所以 stack 删除元素后,minStack 也要考虑是否需要删除元素
// 否则的话,minStack 有可能保存一个 stack 中不存在的元素
// 首先,获取 minStack 的栈顶元素
int top = minStack.peek();
// 再判断 top 这个栈顶元素是否和 stack 移除的元素相等,如果相等,那么需要把 minStack 中的栈顶元素一并移除
if (pop == top) {
// 移除 minStack 的栈顶元素
minStack.pop();
}
}
public int top() {
// 返回 stack 的栈顶元素
return stack.peek();
}
public int getMin() {
// 返回 minStack 的栈顶元素
return minStack.peek();
}
}
2、Python
class MinStack:
def __init__(self):
# 首先定义好两个栈
# 一个栈叫做 stack,负责栈的正常操作
self.stack = []
# 一个栈叫做 min_stack,负责获取 stack 中的最小值,它等价于遍历 stack 中的所有元素,把升序的数字都删除掉,留下一个从栈底到栈顶降序的栈
self.min_stack = []
def push(self, val: int) -> None:
# 新添加的元素添加到 stack 中
self.stack.append(val)
# 判断 min_stack 是否为空,如果为空,直接同时把新添加的元素添加到 minStack 中
# 如果 min_stack 不为空
if self.min_stack:
# 获取 min_stack 的栈顶元素
top = self.min_stack[-1]
# 只有新添加的元素不大于 top 才允许添加到 minStack 中,目的是为了让 minStack 从栈底到栈顶是降序的
if val <= top :
self.min_stack.append(val)
# min_stack 中没有元素,所以直接把新添加的元素添加到 min_stack 中
else:
self.min_stack.append(val)
def pop(self) -> None:
# 让 stack 执行正常的 pop 操作就行
pop = self.stack[-1]
self.stack.pop()
# 由于 minStack 中的所有元素都是来自于 stack 中,所以 stack 删除元素后,minStack 也要考虑是否需要删除元素
# 否则的话,minStack 有可能保存一个 stack 中不存在的元素
# 首先,获取 minStack 的栈顶元素
top = self.min_stack[-1]
# 再判断 top 这个栈顶元素是否和 stack 移除的元素相等,如果相等,那么需要把 minStack 中的栈顶元素一并移除
if pop == top:
# 移除 min_stack 的栈顶元素
self.min_stack.pop()
def top(self) -> int:
# 返回 stack 的栈顶元素
return self.stack[-1]
def getMin(self) -> int:
# 返回 min_stack 的栈顶元素
return self.min_stack[-1]