当前位置: 首页 > news >正文

【Hot100|11-LeetCode 239. 滑动窗口最大值 】

这段代码是解决 LeetCode 239. 滑动窗口最大值 问题的经典单调队列(双端队列)解法,核心目标是在大小为k的滑动窗口从数组左端滑动到右端的过程中,高效获取每个窗口的最大值,时间复杂度优化到 O (n),空间复杂度 O (k)。下面从问题理解→核心思路→代码逐行解析→实例演示四个维度详细讲解:

一、问题理解

问题要求

给定一个整数数组 nums 和一个整数 k,滑动窗口从数组的最左侧移动到最右侧,每次只向右移动一位。请你找出所有滑动窗口中的最大值,并返回这些最大值组成的数组。

例如:输入 nums = [1,3,-1,-3,5,3,6,7]k = 3,滑动窗口的过程及最大值如下:

  • 窗口 [1,3,-1] → 最大值 3
  • 窗口 [3,-1,-3] → 最大值 3
  • 窗口 [-1,-3,5] → 最大值 5
  • 窗口 [-3,5,3] → 最大值 5
  • 窗口 [5,3,6] → 最大值 6
  • 窗口 [3,6,7] → 最大值 7输出:[3,3,5,5,6,7]

二、核心思路:单调队列维护潜在最大值

暴力解法(每次滑动窗口时遍历 k 个元素找最大值)时间复杂度为 O (nk),效率极低。该解法通过双端队列(Deque)维护一个 “单调递减队列”,仅保留窗口中 “可能成为最大值” 的元素,实现线性时间求解,核心思路:

  1. 单调队列的作用:队列中存储数组元素的索引(而非值),且这些索引对应的元素值从队首到队尾单调递减。这样,队首元素对应的数值就是当前窗口的最大值。

  2. 入队规则:当新元素(当前索引i对应的nums[i])进入窗口时,从队尾移除所有值小于等于当前元素的索引(因为这些元素在当前元素右侧,且值更小,永远不可能成为后续窗口的最大值),再将当前索引加入队尾。

  3. 出队规则:当窗口滑动时,若队首元素的索引已在窗口左边界左侧(即不在当前窗口内),则从队首移除该索引。

  4. 记录最大值:当窗口完全形成(即i >= k-1)后,队首元素对应的数值就是当前窗口的最大值,记录到结果数组中。

三、代码逐行解析

java

运行

import java.util.ArrayDeque;
import java.util.Deque;class Solution {public int[] maxSlidingWindow(int[] nums, int k) {int n = nums.length;// 结果数组:滑动窗口的个数为 n - k + 1(如n=8,k=3时,8-3+1=6个窗口)int[] ans = new int[n - k + 1];// 双端队列:存储元素索引,维护队列内元素值单调递减Deque<Integer> q = new ArrayDeque<>();// 遍历数组的每个元素(i为当前元素索引)for (int i = 0; i < n; i++) {// 1. 新元素从队尾入队,维护队列单调性(从队首到队尾递减)// 若队尾元素值 <= 当前元素值,移除队尾(这些元素不可能成为后续窗口最大值)while (!q.isEmpty() && nums[q.getLast()] <= nums[i]) {q.removeLast();}// 将当前元素索引加入队尾q.addLast(i);// 2. 移除窗口外的元素(队首元素若不在当前窗口内,从队首移除)int left = i - k + 1; // 当前窗口的左边界索引(闭区间)if (q.getFirst() < left) { // 队首索引 < 左边界 → 不在窗口内q.removeFirst();}// 3. 当窗口完全形成(left >= 0)时,记录当前窗口最大值(队首元素值)if (left >= 0) {ans[left] = nums[q.getFirst()];}}return ans;}
}

四、实例演示(直观理解过程)

以测试用例 nums = [1,3,-1,-3,5,3,6,7]k = 3 为例,分步演示队列变化和结果填充:

步骤i(当前索引)nums[i]队列操作(维护单调性)队列元素(索引,对应值)窗口左边界 left队首是否在窗口内记录结果(ans [left])
101队列为空,直接入队[0(1)]0 - 3 + 1 = -2无需判断(left<0)无(窗口未形成)
213队尾 0 (1) <= 3 → 移除;队列为空,入队 1 (3)[1(3)]1-3+1=-1无需判断
32-1队尾 1 (3) > -1 → 直接入队 2 (-1)[1(3), 2(-1)]2-3+1=0队首 1 >= 0 → 在窗口内ans[0] = nums[1] = 3
43-3队尾 2 (-1) > -3 → 直接入队 3 (-3)[1(3), 2(-1), 3(-3)]3-3+1=1队首 1 >= 1 → 在窗口内ans[1] = nums[1] = 3
545队尾 3 (-3) <=5 → 移除;队尾 2 (-1)<=5→移除;队尾 1 (3)<=5→移除;队列为空,入队 4 (5)[4(5)]4-3+1=2队首 4 >= 2 → 在窗口内ans[2] = nums[4] =5
653队尾 4 (5) > 3 → 直接入队 5 (3)[4(5),5(3)]5-3+1=3队首 4 >=3 → 在窗口内ans[3] = nums[4] =5
766队尾 5 (3) <=6 → 移除;队尾 4 (5)<=6→移除;队列为空,入队 6 (6)[6(6)]6-3+1=4队首 6 >=4 → 在窗口内ans[4] = nums[6] =6
877队尾 6 (6) <=7 → 移除;队列为空,入队 7 (7)[7(7)]7-3+1=5队首 7 >=5 → 在窗口内ans[5] = nums[7] =7

最终结果ans = [3,3,5,5,6,7],与预期一致。

五、关键细节解析

1. 为什么队列存储索引而非值?

  • 索引可以直接判断元素是否在当前窗口内(通过与左边界left比较),而值无法做到这一点。例如:队首元素值为 3,但如果其索引小于left,说明已不在窗口内,必须移除。

2. 入队时为什么要移除 “小于等于” 当前元素的队尾元素?

  • 假设队尾元素值为x,当前元素值为y,且x <= y。由于yx右侧(索引更大),当窗口滑动时,x会比y更早离开窗口,而y的值更大,因此x永远不可能成为后续窗口的最大值,留着只会占用空间,必须移除。
  • x == y:保留右侧的y(索引更大)更优,因为y能在窗口中存在更久,可能成为后续窗口的最大值。

3. 窗口何时 “完全形成”?

  • i >= k-1时,窗口左边界left = i - k + 1 >= 0,此时窗口包含k个元素(从lefti),可以记录最大值。例如k=3i=2left=0,窗口[0,2]刚好包含 3 个元素。

4. 为什么队首一定是当前窗口的最大值?

  • 队列通过入队规则维护了 “从队首到队尾单调递减” 的特性,即nums[q.getFirst()] >= nums[q.get(1)] >= ... >= nums[q.getLast()]。因此,队首元素对应的数值必然是当前窗口的最大值。

六、复杂度分析

  • 时间复杂度:O(n)。数组中每个元素最多入队一次、出队一次(入队和出队操作在双端队列中是 O (1)),因此总操作次数为 O (n)。

  • 空间复杂度:O(k)。队列中最多存储k个元素(当窗口内元素严格递减时,所有元素都会被保留),因此空间复杂度为 O (k)。

七、总结

该解法的核心是 **“单调队列动态维护窗口内的潜在最大值”:通过入队时的单调性筛选(移除不可能成为最大值的元素)和出队时的边界检查(移除窗口外的元素),确保队首始终是当前窗口的最大值,从而在 O (n) 时间内高效求解。这种 “单调队列” 思路是解决滑动窗口极值问题 ** 的经典范式,可迁移到 “滑动窗口最小值”“滑动窗口内的次大值” 等类似问题中。

http://www.dtcms.com/a/596824.html

相关文章:

  • Linux系统磁盘管理
  • 字节开源InfinityStar框架以32倍速挑战Sora范式
  • 买房签合同流程记录
  • VR新能源体验系统:VR 架起清洁能源的认知之桥
  • Jenkins VS GitLab CI/CD VS Arbess,CI/CD工具选型指南
  • 5.1、Python-字符串
  • 编程软件有哪些 | 常见编程工具及其功能解析
  • MCU中的OSC(Oscillator,振荡器)是什么?
  • 如何搜索公司所有的网站三亚网
  • 物联网最后一节课
  • 稳定币“三明治”:重构全球跨境结算网络
  • 河北省建设注册中心网站手机网页传奇
  • Java学习之旅第三季-23:线程安全(二)
  • 中旅国际数据库国产化升级:以金仓KES打造安全可控的旅游服务底座
  • 推荐一个更好用的C++字符串处理工具类TpString,解决中文字符长度计算等问题!
  • 原识:图注意力与transformer注意力机制对比
  • 注册公司的网站请问怎么做网站
  • 小物暖日常:生活日用品的温柔魔法
  • 光电对抗分类及外场静爆试验操作规程
  • 如何通过代理商申请华为云的免费试用或测试资源?
  • 建设企业网站可信度百度官方网站下载
  • mapbox高阶,使用自定义图层实现立体发光墙体效果
  • 由于图片视频替换和删除导致阿里云上存在大量系统不再使用的文件如何处理
  • 4-ARM-PEG-TCO(2),多臂聚乙二醇衍生物
  • 新化 网站开发万户网络oa
  • 有没有做任务能兑换现金的网站博物馆网站建设必要
  • 算法题(Python)链表篇 | 1.移除链表元素
  • 高速PCB设计指南(0)
  • 建设厅网站ca验证失败山西省大同市网站建设公司
  • 医疗企业网站模板免费下载上海十大设计公司有哪些