定义栈的数据结构,请在该类型中实现一个能够得到栈的最小元素的 min 函数在该栈中,调用 min、push 及 pop 的时间复杂度都是 O(1)。
示例:
MinStack minStack = new MinStack();
minStack.push(-2);
minStack.push(0);
minStack.push(-3);
minStack.min(); --> 返回 -3.
minStack.pop();
minStack.top(); --> 返回 0.
minStack.min(); --> 返回 -2.
我的想法是构建两个列表,一个用来做栈,另一个用作辅助队列,辅助队列里面存放栈中排好序的元素。
对于top来说,只需要返回栈中最上面的元素即可;对于min来说,返回排好序的列表中第一个元素即可。这两个操作并不会增删数据结构中的元素。
对于push来说,我们将新元素压入栈顶,但是如何放入有序列表中,是一件值得思考的事,需要设定好边界条件:
- 如果新元素比有序列表最后一个元素还大,直接append到最后
- 如果新元素等于有序列表第一个元素或者比有序列表第一个元素还小,应该将新元素插入列表下标为0的位置,原来的元素全部向后挪动1个位置
- 如果不在上面两个边界之内,则在有序列表中寻找第一个大于等于x的元素,这个元素怒所在的位置插入新元素,这个元素以后的所有元素向后挪动一个位置。
push正确完成,是pop正常执行的基础,pop不仅要删除stack中的栈顶元素,还要在lst中找到栈顶元素对应的元素,一并删除!
我的这个方法,最关键的问题在于,push操作的边界条件!
边界条件要能覆盖到所有可能,保证逻辑完备性。
class MinStack:
def __init__(self):
"""
initialize your data structure here.
"""
# lst用来记录栈中排好序的元素
self.lst = list()
self.stack = list()
def push(self, x: int) -> None:
self.stack.append(x)
# 在lst中排序
if self.lst:
if self.lst[-1] < x:
self.lst.append(x)
# 请务必确定好边界条件
elif self.lst[0] >= x:
temp = self.lst[:]
self.lst[0] = x
self.lst[1:] = temp
else:
for i in range(len(self.lst)-1):
if self.lst[i] < x and self.lst[i+1] >= x:
temp = self.lst[i+1:]
self.lst[i+1] = x
self.lst[i+2:] = temp
break
else:
self.lst.append(x)
def pop(self) -> None:
self.lst.remove(self.stack[-1])
self.stack.pop()
def top(self) -> int:
return self.stack[-1]
def min(self) -> int:
return self.lst[0]
# 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()
官方题解看起来更精简,也是用了辅助栈,但是时间效率比我的要好很多,因为我的push操作有一个循环操作,时间复杂度是O(n)。官方题解的辅助栈用法是:
-
栈是一种后进先出的数据结构,如果按照a→b→c→d的顺序进栈,无论如何当d在栈顶时,abc都在d的下面,如图所示:
- 因此,对于主栈中的每一层元素,都有一个固定的最小值,因为底下的元素是不会变的。
- 初始化一个min_stack,初始化第一个元素为正无穷大(math.inf),每次在栈中push一个元素,都要比较min_stack的顶层元素与新元素的大小,如果新元素更小,就将新元素添加,如果栈顶元素更小,则将栈顶元素加入。
- 我们可以发现,min_stack中的元素,自下而上看是单调不增的
class MinStack:
def __init__(self):
self.stack = []
self.min_stack = [math.inf]
def push(self, x: int) -> None:
self.stack.append(x)
self.min_stack.append(min(x, self.min_stack[-1]))
def pop(self) -> None:
self.stack.pop()
self.min_stack.pop()
def top(self) -> int:
return self.stack[-1]
def min(self) -> int:
return self.min_stack[-1]