最小栈
力扣第155题 : https://leetcode-cn.com/problems/min-stack/
设计一个支持 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.
最开始的思路
当我看到这道题的时候,因为是求最小的元素,所以我只用了一个变量,想要动态的更新最小值。但是有一个问题就出现了,当我把最小值pop出来后,当前的最小值就又会发生变化了,所以用变量保存最小值不是一个理想的解法。我又想到了再用一个数组来保存最小的的变化信息,当pop的时候在更新最小值。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| class MinStack:
def __init__(self): self.stack = [] self.min_ele = float('inf') self.min_list = [] def push(self, x: int) -> None: self.stack.append(x) self.min_ele = min(self.min_ele, x) if self.min_ele not in self.min_list: self.min_list.append(self.min_ele)
def pop(self) -> None: pop_ele = self.stack.pop() if self.min_ele == pop_ele and pop_ele not in self.stack: self.min_list.pop() if self.min_list: self.min_ele = self.min_list[-1]
def top(self) -> int: if self.stack: return self.stack[-1]
def getMin(self) -> int: return self.min_ele
|
虽然没通过,但是辅助栈的雏形已经出来了
1. 同步的辅助栈
- 上面的代码其实存储最小值的变量是没必要的,因为最小值已经存储在辅助栈里面了
- 当我们在push入栈的时候,同时将该数和辅助栈的栈顶元素比较大小,如果小于栈顶元素,则最小值为该元素,将该元素push入辅助栈中;如果大于栈顶元素,则证明最小值仍为栈顶元素
- 从而实现了主栈和辅助栈永远是同步的,即长度一样,级主栈中每一个元素对应的栈中最小值是正确的.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| class MinStack:
def __init__(self): """ initialize your data structure here. """ self.stack = [] self.min_stack = []
def push(self, x: int) -> None: self.stack.append(x) if not self.min_stack or self.min_stack[-1] > x: self.min_stack.append(x) else: self.min_stack.append(self.min_stack[-1])
def pop(self) -> None: if self.stack: self.stack.pop() self.min_stack.pop()
def top(self) -> int: if self.stack: return self.stack[-1]
def getMin(self) -> int: if self.min_stack: return self.min_stack[-1]
|
1.1 复杂度分析
时间复杂度:,“出栈”、“入栈”、“查看栈顶元素”的操作不论数据规模多大,都只是有限个步骤,因此时间复杂度是:O(1)。
空间复杂度:O(N),这里 N 是读出的数据的个数。
2. 不同步的辅助栈
同步辅助栈虽然很好理解,但是有一个问题就是它为了保持长度跟主栈一样,从而造成了没必要的浪费,所以这里讲一下不同步的辅助栈。
- 不同步辅助栈就是只有在push时该数小于或等于辅助栈的栈顶元素是才push入辅助栈
- 在pop元素之,如果该元素等于辅助栈的栈顶元素,则将辅助栈的栈顶元素pop出来
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| class MinStack:
def __init__(self): """ initialize your data structure here. """ self.stack = [] self.min_stack = []
def push(self, x: int) -> None: self.stack.append(x) if not self.min_stack or self.min_stack[-1] >= x: self.min_stack.append(x)
def pop(self) -> None: if self.stack: top = self.stack.pop() if self.min_stack and top == self.min_stack[-1]: self.min_stack.pop()
def top(self) -> int: if self.stack: return self.stack[-1]
def getMin(self) -> int: if self.min_stack: return self.min_stack[-1]
|
2.1 复杂度分析
时间复杂度:,“出栈”、“入栈”、“查看栈顶元素”的操作不论数据规模多大,都只是有限个步骤,因此时间复杂度是:O(1)。
空间复杂度:O(N),这里 N 是读出的数据的个数
相似题目
最大栈
滑动窗口最大值