算法
(单调栈) $O(1)$
我们除了维护基本的栈结构之外,还需要维护一个单调栈,来实现返回最小值的操作。
下面介绍如何维护单调栈:
- 当我们向栈中压入一个数时,如果该数 $\le$ 单调栈的栈顶元素,则将该数同时压入单调栈中;否则,不压入,这是由于栈具有先进后出性质,所以在该数被弹出之前,栈中一直存在一个数比该数小,所以该数一定不会被当做最小数输出。
- 当我们从栈中弹出一个数时,如果该数等于单调栈的栈顶元素,则同时将单调栈的栈顶元素弹出。
- 单调栈由于其具有单调性,所以它的栈顶元素,就是当前栈中的最小数。
时间复杂度
四种操作都只有常数次入栈出栈操作,所以时间复杂度都是 $O(1)$.
C++ 代码
class MinStack {
public:
/** initialize your data structure here. */
stack<int> stackValue;
stack<int> stackMin;
MinStack() {
}
void push(int x) {
stackValue.push(x);
if (stackMin.empty() || stackMin.top() >= x)
stackMin.push(x);
}
void pop() {
if (stackMin.top() == stackValue.top()) stackMin.pop();
stackValue.pop();
}
int top() {
return stackValue.top();
}
int getMin() {
return stackMin.top();
}
};
/**
* Your MinStack object will be instantiated and called as such:
* MinStack obj = new MinStack();
* obj.push(x);
* obj.pop();
* int param_3 = obj.top();
* int param_4 = obj.getMin();
*/
if(stackMin.empty() || stackMin.top() >= x) 里面 empty()一定要写在前面
y总,如果测试用例是连续三次push,值分别是1,-4,-4,之后是getMin,pop,getMin,答案应该是-4,null,-4才对,按这个代码,答案是-4,null,1,是不是有点问题
按这个代码,答案也是-4,null,-4呀
对滴。
y总,为什么push操作中,必须是
stackMin.top() >= x
的时候才能push,而不是stackMin.top() > x
的时候再push。=x
的时候没意义啊有道理,都可以吧。
不可以。
如果写成
stackMin.top() > x
,那么当先插入多个x,然后再弹出一个x时,我们就不知道该不该从stackMin里弹出x了。明白了,防止重复的数的干扰!
如果插入两个同样大小的min,不写’=’会导致删掉min的后,栈里明明理应存在一个min,但已经被删掉。
y神,我想请问下,如果我入栈时,先判断是否比头小,若小,入栈,大的话,就先取出top,再将入栈,再将前一个top入栈,保证最小值在top的话,复杂度是多少啊
我现在不能确定你的算法是否正确。建议先自己写一下代码,验证其正确性,如果可以通过所有测试数据,可以私信发我看一下代码。
就是入栈的时候,你选择了用stackMin.empty()判断是否为空,但我如果选择另一个satckValue.empty()来判断是否为空,就会报Segmentation Fault错误。有一点疑惑,感觉两个判断是否为空都差不多。
这里写stackMin或者写stackValue是等价的。不过改成stackValue之后需要将stackValue.push(x)语句放到判断语句的后面。
欧克,谢谢!
为什么呢?
我也有这个问题,可是搞不懂原因
这个getmin函数是不是只能获取一次最小值呀?比如输入数据3、-1、2、5,stackmin栈中的数据只有3、-1,依次出栈后最小元素-1,3,但是2要比3小,获取完第一次最小值后如果将-1出栈是不是就无法再次取得最小值了?
出栈的时候会判断
stackMin.top()
和stackValue.top()
的值是否相等,相等的话stackMin.top()
才会出栈,所以当将 5 和 2出栈时,-1并不会从stackMin
里被弹出来。明白了,谢谢(^^)