单调队列的定义与特点
单调队列是一种特殊的队列数据结构,保证队列中的元素始终按照单调递增或递减的顺序排列。常用于解决滑动窗口类问题,能够高效维护区间极值。
单调队列的核心操作包括:
- 入队时移除队尾破坏单调性的元素
- 出队时检查队首元素是否过期
- 始终保证队列头部是当前窗口的最值
实现单调队列的基本模板
class MonotonicQueue:
def __init__(self):
self.q = collections.deque()
def push(self, x):
while self.q and self.q[-1] < x: # 维护单调递减
self.q.pop()
self.q.append(x)
def max(self):
return self.q[0]
def pop(self, x):
if self.q and self.q[0] == x:
self.q.popleft()
典型应用场景:滑动窗口最大值
给定数组和窗口大小k,返回每个窗口的最大值:
def maxSlidingWindow(nums, k):
q = MonotonicQueue()
res = []
for i, num in enumerate(nums):
if i >= k:
q.pop(nums[i - k]) # 移除离开窗口的元素
q.push(num)
if i >= k - 1:
res.append(q.max())
return res
时间复杂度优化至O(n),相比暴力解法O(nk)有显著提升。
算法优化技巧
处理边界条件时需注意:
- 队列存储元素下标而非值,便于判断是否超出窗口范围
- 初始化时先处理前k-1个元素
- 结果收集从第k个元素开始
改进后的实现:
def maxSlidingWindow(nums, k):
q = collections.deque()
res = []
for i in range(len(nums)):
while q and nums[q[-1]] <= nums[i]:
q.pop()
q.append(i)
if q[0] == i - k:
q.popleft()
if i >= k - 1:
res.append(nums[q[0]])
return res
扩展应用场景
单调队列还可用于解决:
- 满足条件的子数组个数统计
- 带限制的子序列和问题
- 二维滑动窗口极值问题
- 某些动态规划优化问题
例如求滑动窗口最小值只需修改比较条件:
while q and nums[q[-1]] >= nums[i]: # 改为维护单调递增
q.pop()
复杂度分析与比较
- 空间复杂度:O(k)的额外空间
- 时间复杂度:每个元素最多入队出队一次,O(n)
- 相比堆结构:获取最值O(1) vs O(logk)
- 相比线段树:实现更简单且常数更小
常见错误与调试建议
容易出现的问题包括:
- 窗口移动时未正确移除过期元素
- 比较条件写反导致单调性错误
- 存储下标但比较时忘记取实际值
- 初始化阶段过早开始收集结果
调试时可打印每个步骤的队列状态,验证:
- 队列是否始终保持单调性
- 队首元素是否始终在窗口范围内
- 结果收集时机是否正确
1174

被折叠的 条评论
为什么被折叠?



