给定数组 a 和窗口大小 k,依次输出每个长度为 k 的子数组的最大值。朴素做法是每个窗口扫一遍,O(n·k)。用单调队列可以压到 O(n)。
单调队列思路
维护一个 deque,里面只保存当前窗口里的有用候选——按下标递增、对应的值严格递减。这样队首永远是当前窗口的最大值。
每移动到一个新位置 i:
- 清理队首:如果队首索引已经离开窗口(
< i - k + 1),弹掉 - 清理队尾:从队尾开始弹出所有
a[?] ≤ a[i]的索引——它们既比a[i]小又更早,永远不可能是后续窗口的最大值 - 入队:把
i压到队尾 - 取答案:如果窗口已经成型(
i ≥ k - 1),队首索引对应的值就是当前窗口的最大
每个索引最多入队、出队各一次,总共 O(n) 次操作。
复杂度
- 时间:O(n)
- 空间:O(k)(deque 最多装 k 个候选)
在动画里看什么
- 数组上方的虚线框是当前窗口
[i - k + 1, i] - 深蓝单元格是刚处理的
a[i];浅蓝是当前在 deque 里的有用候选 - 下方的
deque中,暖红色的就是窗口最大值(队首) result在每次窗口成型时追加一个值