(11)LeetCode 239. 滑动窗口最大值

LeetCode 239. 滑动窗口最大值

题目描述

给你一个整数数组 nums 和一个大小为 k 的滑动窗口,窗口从数组的最左侧移动到最右侧,每次只向右移动一位。返回每个窗口中的最大值。

示例:

输入:nums = 1,3,-1,-3,5,3,6,7, k = 3

输出:3,3,5,5,6,7

解题思路

核心思想: 使用双端队列(deque)维护一个单调递减的下标序列。

  • 队列中存储的是数组下标,且保证这些下标对应的元素值从队首到队尾严格递减。
  • 队首元素对应的值就是当前滑动窗口的最大值。

算法步骤:

  1. 遍历数组,当前下标 i 作为窗口的右边界。
  2. 维护递减性 :若当前元素 nums[i] 大于等于队尾元素对应的值,则队尾元素不可能成为后续窗口的最大值,将其弹出。
  3. 将当前下标 i 从队尾入队。
  4. 移除过期下标 :计算窗口左边界 left = i - k + 1,若队首下标小于 left,说明该元素已滑出窗口,从队首弹出。
  5. 记录答案 :当 left >= 0 时,当前窗口已完整,队首下标对应的值即为最大值,存入结果数组 ans[left]

代码实现(C++)

cpp 复制代码
class Solution {
public:
    vector<int> maxSlidingWindow(vector<int>& nums, int k) {
        int n = nums.size();
        deque<int> q;               // 存储下标,保证值递减
        vector<int> ans(n - k + 1); // 结果数组

        for (int i = 0; i < n; ++i) {
            // 1. 维护队列单调递减
            while (!q.empty() && nums[q.back()] <= nums[i])
                q.pop_back();
            q.push_back(i);

            // 2. 移除窗口外的元素
            int left = i - k + 1;
            if (q.front() < left)
                q.pop_front();

            // 3. 当窗口完整时记录最大值
            if (left >= 0)
                ans[left] = nums[q.front()];
        }
        return ans;
    }
};

复杂度分析

  • 时间复杂度: O(n)
    每个元素最多入队一次、出队一次,总操作次数为 O(n)。
  • 空间复杂度: O(n)
    双端队列最多存储 k 个元素,结果数组需要 O(n - k + 1) 空间。

手动模拟示例

nums = [1,3,-1,-3,5,3,6,7], k = 3 为例:

i numsi 队列状态(存下标) 窗口范围 最大值
0 1 0 - -
1 3 弹出 0,队列 1 - -
2 -1 队列 1,2 0\~2 3
3 -3 队列 1,2,3 1\~3 3
4 5 弹出 3,2,1,队列 4 2\~4 5
5 3 队列 4,5 3\~5 5
6 6 弹出 5,4,队列 6 4\~6 6
7 7 弹出 6,队列 7 5\~7 7

最终输出:[3,3,5,5,6,7]

关键点总结

  • 队列中存储的是下标,而不是元素值,方便判断元素是否滑出窗口。
  • 双端队列从队尾 维护单调性(淘汰较小值),从队首淘汰过期值。
  • 每个窗口的最大值就是队首元素对应的值,获取时间为 O(1)。
相关推荐
kisshyshy15 小时前
🍦 雪糕、食堂、火车厢:三幅漫画吃透栈、队列与链表
javascript·算法
猿人谷1 天前
不只是 CPU 阈值:STAR 如何用 GAT + Transformer 做容器级自动扩缩容?
人工智能·算法
复杂网络1 天前
Stable Diffusion 视觉大模型微调技术深度调研
算法
复杂网络1 天前
基于 Stable Diffusion 架构的视觉大模型代表性工作与原理深度解析
算法
MrZhao4001 天前
Agent Loop 如何用 Hook 扩展:权限、日志与工具拦截
算法
MrZhao4001 天前
Agent 为什么需要 Skills:别把所有知识都塞进 system prompt
算法
JieE2122 天前
LeetCode 101. 对称二叉树|JS 递归 + 迭代双解法,彻底搞懂镜像判断
javascript·算法
JieE2123 天前
LeetCode 56. 合并区间|超清晰 JS 图解思路,面试高频区间题
javascript·算法·面试
Jack204 天前
HarmonyOS开发中错误处理策略:网络异常统一处理
算法
小小杨树4 天前
读懂色彩:拍照调色不再难
算法·计算机视觉·配色