Stack是一种常用的数据结构。除了在数据结构上,栈的概念使用得很广:
函数调用栈
和内存有关的堆栈
数据结构中的栈结构
数据结构中的栈通常包含四种操作:
push 把元素压入栈
pop 把栈顶元素弹出
top 获取栈顶元素
empty 判断栈是否为空
上面的四种操作都在O(1)内完成。那么问题来了,如果我们要为栈添加两个接口max、min分别获取当前栈的最大、最小值且在O(1)内完成,该如何实现呢?
一种直观但错误的思路是:使用两个变量分别保存最大、最小值。错误在于如果我们已经弹出了最大或最小值了,那么该如何确定当前栈的最大或最小值呢?方法肯定有,但无法做到O(1)
解决这个问题,离不开时间、空间的均衡思想。当我们对算法的时间复杂度有更改的要求,可以通过牺牲空间来解决,反之亦然。当然,这不是定理,而是一种实践经验。
我们可以通过两个辅助栈的来分表保存栈各阶段的max、min值。这样一来我们就需要三个基本栈了。我们先来实现一个基本栈,然后慢慢梳理实现过程。
基本栈的实现 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 31 32 33 class Node : def __init__ (self, value ): self.value = value self.next = None class Stack : def __init__ (self ): self._top = None def __repr__ (self ): return '<Stack>' def push (self, value ): elem = Node(value) elem.next = self._top self._top = elem def pop (self ): if not self.empty(): elem = self._top self._top = elem.next return elem.value return None def top (self ): if self.empty(): return None return self._top.value def empty (self ): return self._top is None
空间换时间 我们把能弹出最大最小元素的栈命名为MStack。MStack需要三个基本栈,分别为cstack、maxstack、minstack。cstack像普通栈一样的操作;maxstack每次比较过程只存储当前栈的最大元素(并不是之保存一个最大元素);minstack每次比较过程只存储当前栈的最小元素。三个栈的元素数量是一一对应的。下面见具体实现。
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 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 class MStack : def __init__ (self ): self.cstack = Stack() self.maxstack = Stack() self.minstack = Stack() self.max = None self.min = None def __repr__ (self ): return '<Stack>' def push (self, value ): if self.max is None : self.max = value self.maxstack.push(value) else : if self.max < value: self.maxstack.push(value) self.max = value else : self.maxstack.push(self.max ) if self.min is None : self.min = value self.minstack.push(value) else : if self.min > value: self.minstack.push(value) self.min = value else : self.minstack.push(self.min ) self.cstack.push(value) def top (self ): return self.cstack.top() def pop (self ): self.maxstack.pop() self.minstack.pop() return self.cstack.pop() def getmax (self ): return self.maxstack.top() def getmin (self ): return self.minstack.top()
实现MStack的关机是(1)采用辅助栈保存最大、最小状态(2)push操作处理好当前栈的max、minmax、min