设计一个支持 push,pop,top 操作,并能在常数时间内检索到最小元素的栈。
push(x) -- 将元素 x 推入栈中。
pop() -- 删除栈顶的元素。
top() -- 获取栈顶元素。
getMin() -- 检索栈中的最小元素。
示例:
MinStack minStack = new MinStack();
minStack.push(-2);
minStack.push(0);
minStack.push(-3);
minStack.getMin(); --> 返回 -3.
minStack.pop();
minStack.top(); --> 返回 0.
minStack.getMin(); --> 返回 -2.
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/min-stack
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
符合直觉的方法是,每次对栈进行修改操作(push和pop)的时候更新最小值。然后getMin只需要返回我们计算的最小值即可, top也是直接返回栈顶元素即可。这种做法每次修改栈都需要更新最小值,因此时间复杂度是O(n).
是否有更高效的算法呢?答案是有的。
我们每次入栈的时候,保存的不再是真正的数字,而是它与当前最小值的差(当前元素没有入栈的时候的最小值)。这样我们pop和top的时候拿到栈顶元素再加上上一个最小值即可。另外我们在push和pop的时候去更新min,这样getMin的时候就简单了,直接返回min。
注意上面加粗的“上一个”,不是“当前的最小值”
经过上面的分析,问题的关键转化为“如果求的上一个最小值”,解决这个的关键点在于利用min。
pop或者top的时候:
因为栈顶元素入栈的时候的通过
栈顶元素=真实值-上一个最小的元素
得到的, 而真实值 = min, 因此可以得出上一个最小的元素=真实值-栈顶元素
没有影响
,上一个最小值就是上上个最小值。/*
* @lc app=leetcode id=155 lang=javascript
*
* [155] Min Stack
*/
/**
* initialize your data structure here.
*/
var MinStack = function() {
this.stack = [];
this.min = Number.MAX_VALUE;
};
/**
* @param {number} x
* @return {void}
*/
MinStack.prototype.push = function(x) {
// update 'min'
const min = this.min;
if (x < this.min) {
this.min = x;
}
return this.stack.push(x - min);
};
/**
* @return {void}
*/
MinStack.prototype.pop = function() {
const item = this.stack.pop();
const min = this.min;
if (item < 0) {
this.min = min - item;
return min;
}
return item + min;
};
/**
* @return {number}
*/
MinStack.prototype.top = function() {
const item = this.stack[this.stack.length - 1];
const min = this.min;
if (item < 0) {
return min;
}
return item + min;
};
/**
* @return {number}
*/
MinStack.prototype.getMin = function() {
return this.min;
};
/**
* Your MinStack object will be instantiated and called as such:
* var obj = new MinStack()
* obj.push(x)
* obj.pop()
* var param_3 = obj.top()
* var param_4 = obj.getMin()
*/