c++oding="utf-8" ?>
滑动窗口最大值不能用普通队列,因其无法o(1)删除非队首的过期元素;单调队列用双端队列维护递减序列,队首恒为当前窗口最大值,入队时从队尾弹出更小元素,并需严格检查队空及索引越界。

滑动窗口最大值为什么不能用普通队列
因为普通队列只能从头出、从尾进,无法在 O(1) 时间内删除任意位置的旧值。当窗口滑动时,你得删掉已经移出窗口的元素,但它的位置不在队首——这时候普通队列就得遍历找,退化成 O(n) 每次操作。
单调队列本质是「维护一个递减序列的双端队列」:队首永远是当前窗口最大值,队尾只保留比它小的数,且按索引递增排列。
- 入队前,从队尾开始弹出所有
nums[deque.back()] 的元素(保证严格递减,相等也要弹,否则窗口里多个相同最大值时可能误删) - 入队后,检查队首索引是否已小于
i - k + 1(即已滑出左边界),是则弹出 - 只有当窗口填满(
i >= k - 1)才开始记录nums[deque.front()]
用 deque 实现时最容易漏掉的边界检查
两个关键索引判断必须写全,缺一不可:
if (!dq.empty() && dq.front() —— 队首过期,必须先清while (!dq.empty() && nums[dq.back()] —— 队尾不满足单调性,必须循环清
常见错误是把第二个写成 而不是 <code>:当输入含重复最大值(如 <code>[3,3,3,3]),会导致队列残留旧索引,后续窗口移动后队首可能指向已越界的值,触发越界访问或逻辑错误。
为什么不用 vector 模拟双端队列
vector 的 pop_back() 和 push_back() 是 O(1),但 erase(begin()) 是 O(n)。而单调队列频繁从队首删除,用 vector 会把整体复杂度拉回 O(nk)。
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
deque 在两端增删都是摊还 O(1),且内存不连续但对缓存不敏感——本题每轮只访问队首和队尾,不遍历中间,所以性能损失可忽略。
别被“deque 名字像 double-ended queue 就一定慢”误导;实际在 g++ libstdc++ 中,deque 的常数足够小,远优于手写 vector + offset 模拟。
输出结果数组长度容易算错
窗口大小为 k,数组长 n,合法窗口数量是 n - k + 1,不是 n - k 或 n。
初始化结果 vector 时写成 vector<int> res(n - k + 1)</int>,然后用下标 res[i - k + 1] 填值(当 i >= k - 1);或者更安全地用 res.push_back() 动态追加。
如果输入 k == 1,结果数组长度应为 n;若 k > n,按题意通常视为非法输入,但代码中建议加 if (k > n || k 防崩。
真正难调的 bug 往往藏在索引偏移上:比如把 i - k + 1 错写成 i - k,会导致第一个结果就错位,且后续全部偏移 —— 这种问题不会报错,只会静默输出错误答案。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










