[LeetCode] 155. minStack 设计最小栈
注意:getMin()时间复杂度为O(1)
最原始的方法:
class MinStack(object): def __init__(self): """ initialize your data structure here. """ self.stack=[] def push(self, x): """ :type x: int :rtype: void """ # self.stack.push(x) #无push函数,push操作是用append()函数实现 self.stack.append(x) def pop(self): """ :rtype: void """ self.stack.pop() #直接弹出最顶层元素 def top(self): """ :rtype: int """ return self.stack[-1] def getMin(self): """ :rtype: int """ # return min(self.stack()) return min(self.stack)
可惜min()函数太慢
思路1:
使用2个栈,栈1记录进来的数,栈2记录目前的最小值。当有新数push进来的时候,如果栈2为空或者这个数小于栈2顶上的值,就把这个数推入栈2。当pop的数正好等于最小值时,说明当前栈内的最小值变化了,要弹出这个最小值,记录的下一个最小值来到栈顶。
栈2始终记录着栈1的当前最小值,故pop,push操作时也要一并考虑。
class MinStack(object): def __init__(self): """ initialize your data structure here. """ self.stack=[] self.min_stack=[] def push(self, x): """ :type x: int :rtype: void """ self.stack.append(x) # if self.min_stack==[] or x < self.min_stack[-1] if len(self.min_stack) == 0 or x <= self.min_stack[-1]: self.min_stack.append(x) def pop(self): """ :rtype: void """ if self.stack[-1]==self.getMin(): #函数前要带self self.min_stack.pop() return self.stack.pop() def top(self): """ :rtype: int """ return self.stack[-1] def getMin(self): """ :rtype: int """ return self.min_stack[-1]
运行时间降到了60ms 。
时间复杂度分析:
getMin()和top()都是O(1).
思路2:
只使用1个栈,用一个变量min_val记录当前的最小值,将当前最小值一同入栈,为节省空间,仅在当前最小值更改时才入栈。所以该栈的push和pop实际上可能是两次。当新进来的数小于min_val时,把当前的min_val和新进来的数一起推入到栈,min_val变为这个新进来的数。当pop栈顶元素的时候,如果栈顶元素的值和min_val相等,那么就把它下面记录的之前最小值赋给min_val并弹出。
class MinStack(object): def __init__(self): self.min = 2147483647 self.stack = [] def push(self, x): if x <= self.min: self.stack.append(self.min) self.min = x self.stack.append(x) def pop(self): peak = self.stack.pop() if peak == self.min: self.min = self.stack.pop() def top(self): return self.stack[-1] def getMin(self): return self.min
不过此方法会出现重复值。
思路3:
也是使用1个栈,但栈中存的是当前值与最小值的差,用一个元素来记录,然后根据这个值可以计算出当前值和最小值。当栈顶元素为正时,表示当前元素比最小元素大,当前值为最小值+差值;当栈顶元素为负时,其表示的是当前元素值比之前最小值小,现在的最小值就是元素值。
class MinStack(object): def __init__(self): self.min = 2147483648 self.stack = [] def push(self, x): if not self.stack: self.min = x self.stack.append(x - self.min) if x < self.min: self.min = x def pop(self): peak = self.stack.pop() if peak < 0: self.min = self.min - peak def top(self): if self.stack[-1] < 0: return self.min else: return self.min + self.stack[-1] def getMin(self): return self.min