leecode/problems/155.min-stack.md
2020-05-22 18:17:19 +08:00

305 lines
6.9 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 题目地址
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).
![](https://pic.leetcode-cn.com/7beed41b8dc0325445721a36b7db34e1af902441b67996d2eeadcb1f5a5e33d9.jpg)
是否有更高效的算法呢?答案是有的。
我们每次入栈的时候,保存的不再是真正的数字,而是它与当前最小值的差(当前元素没有入栈的时候的最小值)。
这样我们pop和top的时候拿到栈顶元素再加上**上一个**最小值即可。
另外我们在push和pop的时候去更新min这样getMin的时候就简单了直接返回min。
> 注意上面加粗的“上一个”,不是“当前的最小值”
经过上面的分析问题的关键转化为“如何求得上一个最小值”解决这个的关键点在于利用min。
pop或者top的时候
- 如果栈顶元素小于0说明栈顶是当前最小的元素它出栈会对min造成影响我们需要去更新min。
上一个最小的是“min - 栈顶元素”,我们需要将上一个最小值更新为当前的最小值
> 因为栈顶元素入栈的时候的通过 `栈顶元素 = 真实值 - 上一个最小的元素` 得到的,
而真实值 = min 因此可以得出`上一个最小的元素 = 真实值 -栈顶元素`
- 如果栈顶元素大于0说明它对最小值`没有影响`,上一个最小值就是上上个最小值。
![](https://pic.leetcode-cn.com/7da0473d92d70bb47ce7b62303c062e5f517b09d1bf501c4ad341b65415d5c43.jpg)
![](https://pic.leetcode-cn.com/aefec54238c942c484837ea6c724304fb179d3d64f110481d955d9eea65c4fc5.jpg)
## 关键点
- 最小栈存储的不应该是真实值而是真实值和min的差值
- top的时候涉及到对数据的还原这里千万注意是**上一个**最小值
## 代码
* 语言支持JSPython
Javascript Code:
```js
/*
* @lc app=leetcode id=155 lang=javascript
*
* [155] Min Stack
*/
/**
* initialize your data structure here.
*/
var MinStack = function() {
this.stack = [];
this.minV = Number.MAX_VALUE;
};
/**
* @param {number} x
* @return {void}
*/
MinStack.prototype.push = function(x) {
// update 'min'
const minV = this.minV;
if (x < this.minV) {
this.minV = x;
}
return this.stack.push(x - minV);
};
/**
* @return {void}
*/
MinStack.prototype.pop = function() {
const item = this.stack.pop();
const minV = this.minV;
if (item < 0) {
this.minV = minV - item;
return minV;
}
return item + minV;
};
/**
* @return {number}
*/
MinStack.prototype.top = function() {
const item = this.stack[this.stack.length - 1];
const minV = this.minV;
if (item < 0) {
return minV;
}
return item + minV;
};
/**
* @return {number}
*/
MinStack.prototype.min = function() {
return this.minV;
};
/**
* 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.min()
*/
```
Python Code:
```python
class MinStack:
def __init__(self):
"""
initialize your data structure here.
"""
self.minV = float('inf')
self.stack = []
def push(self, x: int) -> None:
self.stack.append(x - self.minV)
if x < self.minV:
self.minV = x
def pop(self) -> None:
if not self.stack:
return
tmp = self.stack.pop()
if tmp < 0:
self.minV -= tmp
def top(self) -> int:
if not self.stack:
return
tmp = self.stack[-1]
if tmp < 0:
return self.minV
else:
return self.minV + tmp
def min(self) -> int:
return self.minV
# Your MinStack object will be instantiated and called as such:
# obj = MinStack()
# obj.push(x)
# obj.pop()
# param_3 = obj.top()
# param_4 = obj.min()
```
**复杂度分析**
- 时间复杂度O(1)
- 空间复杂度O(1)
# 两个栈
## 思路
我们使用两个栈:
- 一个栈存放全部的元素pushpop都是正常操作这个正常栈。
- 另一个存放最小栈。 每次push如果比最小栈的栈顶还小我们就push进最小栈否则不操作
- 每次pop的时候我们都判断其是否和最小栈栈顶元素相同如果相同那么我们pop掉最小栈的栈顶元素即可
## 关键点
- 往minstack中 push的判断条件。 应该是stack为空或者x小于等于minstack栈顶元素
## 代码
JavaScript
```js
/**
* initialize your data structure here.
*/
var MinStack = function() {
this.stack = []
this.minStack = []
};
/**
* @param {number} x
* @return {void}
*/
MinStack.prototype.push = function(x) {
this.stack.push(x)
if (this.minStack.length == 0 || x <= this.minStack[this.minStack.length - 1]) {
this.minStack.push(x)
}
};
/**
* @return {void}
*/
MinStack.prototype.pop = function() {
const x = this.stack.pop()
if (x !== void 0 && x === this.minStack[this.minStack.length - 1]) {
this.minStack.pop()
}
};
/**
* @return {number}
*/
MinStack.prototype.top = function() {
return this.stack[this.stack.length - 1]
};
/**
* @return {number}
*/
MinStack.prototype.min = function() {
return this.minStack[this.minStack.length - 1]
};
/**
* 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.min()
*/
```
Python3:
```python
class MinStack:
def __init__(self):
"""
initialize your data structure here.
"""
self.stack = []
self.minstack = []
def push(self, x: int) -> None:
self.stack.append(x)
if not self.minstack or x <= self.minstack[-1]:
self.minstack.append(x)
def pop(self) -> None:
tmp = self.stack.pop()
if tmp == self.minstack[-1]:
self.minstack.pop()
def top(self) -> int:
return self.stack[-1]
def min(self) -> int:
return self.minstack[-1]
# Your MinStack object will be instantiated and called as such:
# obj = MinStack()
# obj.push(x)
# obj.pop()
# param_3 = obj.top()
# param_4 = obj.min()
```
**复杂度分析**
- 时间复杂度O(1)
- 空间复杂度O(N)