#include <vector>
#include <deque>
using namespace std;

class Solution {
  public:
    vector<int> maxInWindows(vector<int>& num, int size) {
        vector<int> result;
        if (size == 0 || size > num.size()) {
            return result;
        }

        deque<int> dq; // 存储索引,保证队列中的索引对应的元素是单调递减的

        for (int i = 0; i < num.size(); i++) {
            // 移除超出当前窗口范围的索引
            if (!dq.empty() && dq.front() < i - size + 1) {
                dq.pop_front();
            }

            // 维护双端队列的单调递减特性
            // 从队列尾部移除所有小于当前元素的索引
            while (!dq.empty() && num[dq.back()] < num[i]) {
                dq.pop_back();
            }

            // 将当前索引加入队列
            dq.push_back(i);

            // 当窗口完全形成时(即i >= size-1),记录当前窗口的最大值
            if (i >= size - 1) {
                result.push_back(num[dq.front()]);
            }
        }

        return result;
    }
};

算法思路详解:
1.边界情况处理:
如果窗口大小为0或大于数组长度,直接返回空结果
2.双端队列的使用:
使用双端队列存储数组元素的索引而不是值
队列中的索引对应的元素值保持单调递减的顺序
队列前端始终是当前窗口的最大值的索引
3.遍历过程中的操作:
移除过期元素:检查队列前端的索引是否还在当前窗口范围内,如果不在就移除
维护单调性:从队列尾部移除所有对应值小于当前元素的索引,因为它们不可能成为后续窗口的最大值
添加当前元素:将当前元素的索引加入队列尾部
4.记录结果:当遍历到足够形成完整窗口的位置时,将队列前端的值(当前窗口的最大值)加入结果

时间复杂度分析:
每个元素最多被压入和弹出队列各一次
因此总体时间复杂度为O(n)

空间复杂度分析:
双端队列最多存储size个元素
结果数组存储n-size+1个元素
因此空间复杂度为O(n)
  
  关键变量含义:
i:当前遍历到的数组索引
size:滑动窗口大小
dq.front():双端队列前端的索引(当前窗口最大值的候选索引)
i - size + 1:当前窗口的起始位置

也可以分成两部分循环,因为只有i>=k是才会需要移除超出当前窗口范围的索引
#include <vector>
#include <deque>

using namespace std;

class Solution {
public:
    vector<int> maxSlidingWindow(vector<int>& nums, int k) {
        vector<int> res;
        if (k == 0 || k > nums.size()) return res;
        deque<int> dq;
        for (int i = 0; i < k; ++i) {
            while (!dq.empty() && nums[dq.back()] < nums[i]) {
                dq.pop_back();
            }
            dq.push_back(i);
        }
        res.push_back(nums[dq.front()]);
        for (int i = k; i < nums.size(); ++i) {
            while (!dq.empty() && i - dq.front() + 1 > k) {
                dq.pop_front();
            }
            while (!dq.empty() && nums[dq.back()] < nums[i]) {
                dq.pop_back();
            }
            dq.push_back(i);
            res.push_back(nums[dq.front()]);
        }
        return res;
    }
};