单调队列
一、问题引入
1.1 概念介绍
RMQ(x,y) 就是询问数组【x, y】区间内部的最小值, 例如RMQ(0,3) = 1 RMq(3,7) =2
满足任何需求是指:RMQ(0,7) = 1, RMQ(1,7) = 1 , RMQ(2,7) = 2等等, 记录4个值,即可所有RMQ(x, 7 )
1 2 8 12 , 固定末尾查询的最小值队列, 单调递增的序列。
单调队列应用于: 区间最值问题。建立两者的联系。
1.2 队列操作
元素性质: 队首元素,永远维护当前区间的(最大/最小)值。
- 维护区间最小值: 维护递增序列.
- 维护区间最大值: 维护递减序列
二、习题练习
2.1 滑动窗口最大值
class Solution(object):
def maxSlidingWindow(self, nums, k):
"""
:type nums: List[int]
:type k: int
:rtype: List[int]
"""
# 使用一个递减队列 维护最大值
queue = collections.deque()
result = []
for i in range(len(nums)):
# 出队操作, 违反递减性
while (len(queue) != 0 and nums[queue[-1]] < nums[i] ): queue.pop()
# 入队操作
queue.append(i)
# 队首的出队操作
if i - queue[0] == k: queue.popleft()
if i < k-1: continue
result.append(nums[queue[0]])
return result
2.2 队列的最大值
在结构中增加一个单调队列数据结构,来维护最大值。 单调递减的序列
如何判断头部弹出, 何时表示队首元素不在滑动区间?
class MaxQueue(object):
def __init__(self):
self.data = collections.deque()
self.m_queue = collections.deque()
def max_value(self):
"""
:rtype: int
"""
if len(self.data) == 0:
return -1
else:
return self.m_queue[0]
def push_back(self, value):
"""
:type value: int
:rtype: None
"""
self.data.append(value)
while self.m_queue and self.m_queue[-1] < value : self.m_queue.pop()
self.m_queue.append(value)
def pop_front(self):
"""
:rtype: int
"""
if len(self.data) == 0:
return -1
if self.data[0] == self.m_queue[0]: self.m_queue.popleft()
return self.data.popleft()