题目链接:
题目描述:
解题思路:
看到这个问题, 我们的第一反应可能是每次压入一个新元素进栈时, 将栈里的所有元素排序, 让最小的元素位于栈顶, 这样就能在0(1)时间得到最小元素了。 但这种思路不能保证最后压入栈的元素能够最先出栈, 因此这个数据结构已经不是栈了。
我们接着想到在栈里添加一个成员变量存放最小的元素。 每次压入一个新元素进栈的时候,如果该元素比当前最小的元素还要小,则更新最小元素。 面试官听到这种思路之后就会问: 如果当前最小的元素被弹出栈了, 如何得到下一个最小的元素呢?
分析到这里我们发现仅仅添加一个成员变量存放最小元素是不够的,也就是说当最小元素被弹出栈的时候, 我们希望能够得到次小元素。 因此在压入这个最小元素之前, 我们要把次小元素保存起来。
是不是可以把每次的最小元素(之前的最小元素和新压入栈的元素两者的较小值)都保存起来放到另外一个辅助栈里呢?我们不妨举几个例子来分析一下把元素压入或者弹出栈的过程(如表1所示)。
首先住空的数据栈里压入数字3, 显然现在3是最小值, 我们也把这个最小值压入辅助栈。 接下来往数据栈里压入数字4。 由于4大于之前的最小值, 因此我们仍然往辅助栈里压入数字3。第三步继续往数据栈里压入数字2。由于2 小于之前的最小值 3,因此我们把最小值更新为2,并把2压入辅助栈。同样当压入数字1时,也要更新最小值,并把新的最小值1压入辅助栈。
步骤 | 操作 | 数据栈 | 辅助栈 | 最小值 |
1 | 压入3 | 3 | 3 | 3 |
2 | 压入4 | 3、4 | 3、3 | 3 |
3 | 压入2 | 3、4、2 | 3、3、2 | 2 |
4 | 压入1 | 3、4、2、1 | 3、3、2、1 | 1 |
5 | 弹出 | 3、4、2 | 3、3、2 | 2 |
6 | 弹出 | 3、4 | 3、3 | 3 |
7 | 压入0 | 3、4、0 | 3、3、0 | 0 |
从表1中我们可以看出,如果每次都把最小元素压入辅助栈,那么就能保证辅助栈的栈顶一直都是最小元素。当最小元素从数据栈内被弹出之后, 同时弹出辅助栈的栈顶元素,此时辅助栈的新栈顶元素就是下一个最小值。比如第四步之后,栈内的最小元素是1。当第五步在数据栈内弹出1后,我们把辅助栈的栈顶弹出, 辅助栈的栈顶元素2就是新的最小元素。接下来继续弹出数据栈和辅助栈的栈顶之后,数据栈还剩下 3、4 两个数字,3是最小值。 此时位于辅助栈的栈顶数字正好也是3,的确是最小值。 这说明我们的思路是正确的。
已经AC的代码:
'''
题目:定义栈的数据结构,请在该类型中实现一个能够得到栈中所含最小元素的min函数(时间复杂度应为O(1))。
'''
class Solution:
def __init__(self):
self.stack = []
self.minStack = []
self.min_num = None
def push(self, node):
# write code here
self.stack.append(node)
if self.min_num is None:
self.min_num = node
self.minStack.append(self.min_num)
elif self.min_num < node:
self.minStack.append(self.min_num)
else:
self.min_num = node
self.minStack.append(node)
def pop(self):
# write code here
if len(self.stack) > 0 and len(self.minStack):
self.minStack.pop()
self.stack.pop()
def top(self):
# write code here
return
def min(self):
# write code here
return self.minStack[-1]
if __name__ == '__main__':
stack = Solution()
current_stack = [11, 7, 8, 9, 5, 12, 15]
for num in (current_stack):
stack.push(num)
print(stack.min(), stack.stack)
print(stack.minStack)
# 测试用例
# 输入一个比最小值大的
stack.push(7)
print(stack.min(), stack.stack)
# 输入一个比最小值小的
stack.push(4)
print(stack.min(), stack.stack)
# 弹出最小值
stack.pop()
print(stack.min(), stack.stack)
# 弹出非最小值
stack.pop()
print(stack.min(), stack.stack)