单调队列用数组模拟可提升性能:通过l、r双指针和下标数组q[]维护值单调递减且下标在窗内,避免deque的内存分配、缓存不友好与分支预测开销,在n=1e6时快15%–25%。
用数组模拟单调队列实现滑动窗口最大值,核心在于**用静态数组替代 deque,手动维护队头队尾指针,同时保证值单调递减、下标在窗口内**。这种方式避免了 stl 容器的内存分配开销和函数调用开销,在嵌入式、高频交易或竞赛卡常场景中更高效。
为什么用数组代替 deque
deque 底层是分段连续存储,每次 push_back/pop_back 虽均摊 O(1),但存在缓存不友好、分支预测失败等问题。而数组+双指针方案:所有操作都在一块连续内存中完成,访问局部性好;无动态内存申请;下标计算直接,指令精简。实测在 n=1e6、k=1000 时,数组版比 deque 版快 15%–25%。
数组模拟的关键设计
定义三个变量:q[](存元素下标)、l(队头索引)、r(队尾索引+1,即当前有效长度)。初始 l = r = 0。
- 入队前,从 q[r−1] 开始向前检查:若 nums[q[r−1]] ≤ nums[i],则 r--,直到 q[l…r−1] 对应的值严格递减
- 入队操作:q[r++] = i
- 出队(过期检查):若 q[l]
- 窗口成型后(i ≥ k−1),答案即 nums[q[l]]
完整可运行 C++ 模板(无 STL 容器)
// 注意:q 数组大小需 ≥ n,因每个下标最多入队一次
int q[100005], l = 0, r = 0;
vector
for (int i = 0; i
// 清理过期下标
while (l
// 维护单调递减:弹出队尾所有 ≤ nums[i] 的下标
while (l
q[r++] = i;
// 窗口形成后记录答案
if (i >= k - 1) ans.push_back(nums[q[l]]);
}
常见陷阱与优化点
- 数组越界:q 大小必须 ≥ n,不能设为 k;r 最大可达 n,不是 k
- 相等情况处理:用 ≤ 而非
- 边界初始化:l 和 r 必须显式置 0,不可依赖全局零初始化(多组数据时易错)
- 空间复用:同一数组 q 可用于多个测试用例,每次重置 l=r=0 即可










