题目:
设计一个支持 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
次
思路一
为了实现能在常数时间内检索到最小的元素,我们需要一个数据栈和一个最小栈,具体实现方法如下:
- 最小栈入栈规则
- 当前要入栈的数据data,如果当前最小栈为空或者data小于最小栈栈顶元素,则最小栈入data元素。
- 当前要入栈的数据data,如果data大于或者等于最小栈栈顶元素,则最小栈入最小栈栈顶元素。
- 最小栈出栈规则
- 当数据栈要出栈时,最小栈也要跟着出栈。
这样设计最小栈入栈出栈规则就能够保证,当前最小栈的栈顶元素就是栈的最小元素。
AC代码
class MinStack {
public:
MinStack() {
//默认构造
}
void push(int val) {
_st.push(val);
if (_minst.empty() || val < _minst.top())
{
_minst.push(val);
}
else
{
_minst.push(_minst.top());
}
}
void pop() {
_st.pop();
_minst.pop();
}
int top() {
return _st.top();
}
int getMin() {
return _minst.top();
}
private:
stack<int> _st;
stack<int> _minst;
};
思路二
看下图可以发现,如果入栈的元素中存在大量比已经入栈的元素要大,如果按照思路一的想法,则最小栈中就会出现许多连续并且相同的元素,我们可不可以将这同一份元素在最小栈中只出现一次?
因此我们需要改变最小栈的入栈出栈规则:
- 最小栈入栈规则:
- 入栈的元素为data,当最小栈为空或者data小于或者等于最小栈的栈顶元素,最小栈入data元素。
- 入栈的元素为data,当data大于最小栈的栈顶元素,则不做任何操作。
- 最小栈出栈规则:
- 当数据栈的栈顶元素等于最小栈的栈顶元素时,最小栈出栈。
- 当数据栈的栈顶元素不等于最小栈的栈顶元素时,则不做任何操作。
AC代码
class MinStack {
public:
MinStack() {
//默认构造
}
void push(int val) {
_st.push(val);
if (_minst.empty() || val <= _minst.top())
{
_minst.push(val);
}
}
void pop() {
if (_st.top() == _minst.top())
{
_minst.pop();
}
_st.pop();
}
int top() {
return _st.top();
}
int getMin() {
return _minst.top();
}
private:
stack<int> _st;
stack<int> _minst;
};