高效解决滑动窗口最值问题与动态规划优化
单调队列是一种特殊的双端队列(Deque),其内部元素具有严格的单调递增或单调递减性。它常用于在 $O(N)$ 时间复杂度内解决如下问题:
给定一个长度为 $N$ 的数组 $A$ 和一个大小为 $k$ 的滑动窗口。窗口从数组最左侧滑到最右侧,每次向右移动一位。输出窗口在每个位置时的最大值。
普通暴力算法:每个窗口内扫描最值,时间复杂度为 $O(N \times k)$。
单调队列算法:每个元素最多入队一次、出队一次,均摊时间复杂度为极其高效的 $O(N)$。
vector<int> maxSlidingWindow(vector<int>& arr, int k) {
vector<int> res;
deque<int> q; // 双端队列,存储数组索引
for (int i = 0; i < arr.size(); i++) {
// 1. 弹出已滑出窗口范围的队头元素
if (!q.empty() && q.front() <= i - k) {
q.pop_front();
}
// 2. 弹出队尾所有小于当前值的元素,维护队列的单调性
while (!q.empty() && arr[q.back()] < arr[i]) {
q.pop_back();
}
// 3. 将当前元素的索引压入队尾
q.push_back(i);
// 4. 当窗口形成后,记录当前窗口的最大值(即队头对应的元素)
if (i >= k - 1) {
res.push_back(arr[q.front()]);
}
}
return res;
}