offer_30 包含min函数的栈 Offer 59 - II. 队列的最大值
本文对上述两个题目做适当延申,如何模拟求队列和栈的最小值和最大值。
重点:要实现min/max 的时间复杂度为O(1) 故增加一个辅助列表
两个任务各个函数复杂度: 时间复杂度:O(1) 空间复杂度:O(n)
分析举例:(延申的代码没实现 各实现了一个)
# 求队列最大值的话 则
q1 = [-2 0 -3] q2 = [-2 0]
q1 = [5 8 6 3 7 4] 5是队头 q2 = [8 7 4] 最大值取第一个值 递减列表
* 当新进来的值比较大时 需要将它前边的比它小值都pop出去 若新进来的值较小 直接加入
# 【延申】 求队列最小值的话 则
q1 = [5 8 6 3 7 4] 5是队头 q2 = [3 4] 最小值取第一个值 递增列表
* 当新来的值比较小时 需要将它前边的比它大的值都pop出去 若新来的值比较大 直接加入
# 求栈最小值
s1 = [5 8 6 3 7 4] 4是栈顶 s2 = [5 3] 递减列表
#【延申】 求栈最大值的话 则
s1 = [5 8 6 3 7 4] 4是栈顶 s2 = [5 8] 递增列表
队列的最小最大值(线性时间复杂度):
'''
题目:请定义一个队列并实现函数 max_value 得到队列里的最大值,要求函数max_value、push_back 和 pop_front 的均摊时间复杂度都是O(1)。
思路:
⭐ 还有由列表来模拟
⭐ 函数max_value如果需实现时间复杂度为O(1) 则同样需要一个有序队列 来记录顺序的较大值 此处我们使用递减列表
例:
# 求队列最大值的话 则
q1 = [-2 0 -3] q2 = [-2 0]
q1 = [5 8 6 3 7 4] 5是队头 q2 = [8 7 4] 最大值取第一个值 递减列表
* 当新进来的值比较大时 需要将它前边的比它小值都pop出去 若新进来的值较小 直接加入
# 【延申】 求队列最小值的话 则
q1 = [5 8 6 3 7 4] 5是队头 q2 = [3 4] 最小值取第一个值 递增列表
* 当新来的值比较小时 需要将它前边的比它大的值都pop出去 若新来的值比较大 直接加入
各个函数的复杂度: 时间复杂度O(1) 空间复杂度O(n)
'''
class MaxQueue(object):
def __init__(self):
self.q1, self.q2 = [], []
def max_value(self):
"""
:rtype: int
"""
if not self.q2:
return -1
else:
return self.q2[0]
# 要保证 q2中的元素记录的是递减序列 如 [5 8 6 1 7] 记录的是 [8 7] 这就要求当新进来的值比较大时 需要将它前边的比它小值都pop出去 若新进来的值较小 直接加入
def push_back(self, value):
"""
:type value: int
:rtype: None
"""
if not value:
return
self.q1.append(value)
# 列表不为空 且 新元素大于q2中最后一个元素
while self.q2 and self.q2[-1] < value:
self.q2.pop()
self.q2.append(value)
def pop_front(self):
"""
:rtype: int
"""
if not self.q1:
return -1
else:
temp = self.q1.pop(0)
if self.q2 and temp == self.q2[0]:
self.q2.pop(0)
return temp
obj = MaxQueue()
obj.push_back(1)
obj.push_back(2)
print(obj.max_value())
print(obj.pop_front())
print(obj.max_value())
栈的最小最大值(线性时间复杂度):
'''
题目:定义栈的数据结构,请在该类型中实现一个能够得到栈的最小元素的 min 函数在该栈中,调用 min、push 及 pop 的时间复杂度都是 O(1)。
思路:
⭐ 栈使用python中的 列表(pop ) 来模拟
⭐ 其中push和pop的时间复杂度都是O(1) 如果直接调用list中的min 则其时间复杂度为O(n) 所以目前要考虑如何设计使得min函数的时间复杂度为O(1)
⭐ 最简单的想法是增加一个变量 专门用来记录栈中的最小值 但是如果该值被pop出去 则次小值还得再找,所以应该记录一个有序列表(我们记录为一个辅助栈 一个降序列表)
例:
# 求栈最小值
s1 = [5 8 6 3 7 4] 4是栈顶 s2 = [5 3] 递减列表
#【延申】 求栈最大值的话 则
s1 = [5 8 6 3 7 4] 4是栈顶 s2 = [5 8] 递增列表
各个函数的复杂度: 时间复杂度O(1) 空间复杂度O(n)
'''
class MinStack(object):
def __init__(self):
"""
initialize your data structure here.
"""
self.s1 = []
self.s2 = []
def push(self, x):
"""
:type x: int
:rtype: None
"""
self.s1.append(x)
if not self.s2 or self.s2[-1] >= x:
self.s2.append(x)
def pop(self):
"""
:rtype: None
"""
temp = self.s1.pop(-1)
if temp == self.s2[-1]:
self.s2.pop()
return temp
def top(self):
"""
:rtype: int
"""
if self.s1:
return self.s1[-1]
else:
return []
def min(self):
"""
:rtype: int
"""
if self.s1:
return self.s2[-1]
else:
return []
obj = MinStack()
obj.push(-2)
obj.push(0)
obj.push(-3)
print(obj.pop())
param_3 = obj.top()
param_4 = obj.min()
print(param_3)
print(param_4)