## 题目地址 https://leetcode.com/problems/min-stack/description/ ## 题目描述 ``` Design a stack that supports push, pop, top, and retrieving the minimum element in constant time. push(x) -- Push element x onto stack. pop() -- Removes the element on top of the stack. top() -- Get the top element. getMin() -- Retrieve the minimum element in the stack. Example: MinStack minStack = new MinStack(); minStack.push(-2); minStack.push(0); minStack.push(-3); minStack.getMin(); --> Returns -3. minStack.pop(); minStack.top(); --> Returns 0. minStack.getMin(); --> Returns -2. ``` ## 思路 符合直觉的方法是,每次对栈进行修改操作(push和pop)的时候更新最小值。 然后getMin只需要返回我们计算的最小值即可, top也是直接返回栈顶元素即可。 这种做法每次修改栈都需要更新最小值,因此时间复杂度是O(n). ![155.min-stack](../assets/problems/155.min-stack-1.png) 是否有更高效的算法呢?答案是有的。 我们每次入栈的时候,保存的不再是真正的数字,而是它与当前最小值的差(当前元素没有入栈的时候的最小值)。 这样我们pop和top的时候拿到栈顶元素再加上**上一个**最小值即可。 另外我们在push和pop的时候去更新min,这样getMin的时候就简单了,直接返回min。 > 注意上面加粗的“上一个”,不是“当前的最小值” 经过上面的分析,问题的关键转化为“如果求的上一个最小值”,解决这个的关键点在于利用min。 pop或者top的时候: - 如果栈顶元素小于0,说明栈顶是当前最小的元素,它出栈会对min造成影响,我们需要去更新min。 上一个最小的是“min - 栈顶元素”,我们需要将上一个最小值更新为当前的最小值 > 因为栈顶元素入栈的时候的通过 `栈顶元素 = 真实值 - 上一个最小的元素` 得到的, 而真实值 = min, 因此可以得出`上一个最小的元素 = 真实值 -栈顶元素` - 如果栈顶元素大于0,说明它对最小值`没有影响`,上一个最小值就是上上个最小值。 ![155.min-stack-2](../assets/problems/155.min-stack-2.png) ![155.min-stack-3](../assets/problems/155.min-stack-3.png) ## 关键点 - 最小栈存储的不应该是真实值,而是真实值和min的差值 - top的时候涉及到对数据的还原,这里千万注意是**上一个**最小值 ## 代码 ```js /* * @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() */ ```