单调队列的定义与特点
单调队列是一种特殊的队列数据结构,保证队列中的元素始终按照某种单调性(递增或递减)排列。与普通队列不同,单调队列在插入新元素时会移除破坏单调性的元素,从而高效维护队列的单调性。
单调队列的核心操作
初始化
通常使用双端队列(如C++的deque)实现,方便两端操作。
插入元素
以维护递减队列为例:
- 从队尾开始,移除所有小于当前待插入元素的队尾元素。
- 将新元素插入队尾。
例如插入元素x的伪代码:
while (!dq.empty() && dq.back() < x) dq.pop_back();
dq.push_back(x);
删除元素
若队首元素超出滑动窗口范围或其他条件,需移除队首元素:
if (!dq.empty() && dq.front() == out_of_range_value) dq.pop_front();
典型应用场景
滑动窗口最大值
问题描述:给定数组和窗口大小k,返回每个窗口的最大值。
解法:
- 维护递减单调队列,队首即为当前窗口最大值。
- 滑动窗口时,移除左边界元素(若等于队首),并插入新元素。
def maxSlidingWindow(nums, k):
from collections import deque
dq = deque()
res = []
for i, num in enumerate(nums):
while dq and nums[dq[-1]] < num:
dq.pop()
dq.append(i)
if dq[0] == i - k:
dq.popleft()
if i >= k - 1:
res.append(nums[dq[0]])
return res
优化动态规划问题
在某些DP问题中,单调队列可以优化状态转移。例如:
- 问题:
dp[i] = max(dp[j] + f(i-j)),其中j在某个区间内。 - 优化:用单调队列维护
dp[j] + f(i-j)的极值,避免重复计算。
复杂度分析
- 时间复杂度:每个元素最多入队和出队一次,均摊复杂度为$O(n)$。
- 空间复杂度:$O(k)$,其中$k$为队列最大长度(如滑动窗口大小)。
注意事项
- 边界处理:需检查队列是否为空再进行操作。
- 元素重复:若存在重复值,队列中存储下标而非值,避免误删。
- 单调性选择:根据问题需求选择递增或递减队列。
257

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



