LeetCode 239 滑动窗口最大值

点此看全部题解 LeetCode必刷100题:一份来自面试官的算法地图(题解持续更新中)
更多干货,请关注公众号【忍者算法】,回复【刷题清单】获取完整题解目录~

用生活中的例子来理解

想象你是一位摄影师,在拍摄一场马拉松比赛。你的相机一次只能拍摄3个跑步者(就像一个宽度为3的窗口)。随着比赛进行,你的镜头不断向前移动,每次只移动一点点,要在每张照片中找出最高的那位跑步者的身高。这就是我们今天要解决的"滑动窗口最大值"问题。

问题是什么

LeetCode第239题给我们一个任务:假设有一个数组,比如 [2,3,4,2,6,2,5,1],然后给我们一个宽度为3的窗口。这个窗口会从左往右滑动,每次移动一格。我们需要记录下每个窗口中的最大值。

举个简单的例子:

数组:[2,3,4]  窗口大小:2

第一个窗口:[2,3] 4   最大值是3
第二个窗口:2 [3,4] 最大值是4 所以最终结果是:[3,4]

最简单的解决方案:看一看比一比

就像我们肉眼看照片找最高的人一样,最简单的方法就是每次都看窗口里的所有数字,找出最大的那个。

// 这是最容易理解的方法
public int[] maxSlidingWindow(int[] nums, int k) {
int[] result = new int[nums.length - k + 1]; // 存放结果 // 对每个窗口进行处理
for (int i = 0; i <= nums.length - k; i++) {
int max = nums[i]; // 假设窗口第一个数是最大的 // 看看窗口里其他数是不是更大
for (int j = 1; j < k; j++) {
if (nums[i + j] > max) {
max = nums[i + j];
}
} result[i] = max; // 记录这个窗口的最大值
} return result;
}

这个方法很直观,就像用眼睛一个一个数字比较。但是,如果数组很长,窗口很大,这样做就会很慢。

聪明的解决方案:排队游戏

现在我们来学一个更聪明的方法。想象一个游戏:

  1. 我们有一群小朋友排队,每个小朋友手里举着一个数字牌。
  2. 我们要保证队伍里的小朋友,从前到后手里的数字是从大到小的。
  3. 当新的小朋友要进队时,就要把队伍后面所有比他数字小的小朋友请出队。
  4. 队伍最前面的小朋友,就是当前窗口的最大值。

用代码来实现这个想法:

public int[] maxSlidingWindow(int[] nums, int k) {
// 如果数组是空的,直接返回空数组
if (nums == null || nums.length == 0) return new int[0]; int[] result = new int[nums.length - k + 1]; // 存放结果
Deque<Integer> queue = new LinkedList<>(); // 这就是我们的"队伍" for (int i = 0; i < nums.length; i++) {
// 第一步:如果队伍最前面的小朋友已经不在窗口范围内了,请他离开
if (!queue.isEmpty() && queue.peek() < i - k + 1) {
queue.poll();
} // 第二步:新小朋友要入队,
// 把队尾所有比新小朋友数字小的都请出队
while (!queue.isEmpty() && nums[queue.peekLast()] < nums[i]) {
queue.pollLast();
} // 第三步:新小朋友入队
queue.offer(i); // 第四步:如果窗口已经形成,记录当前最大值
if (i >= k - 1) {
result[i - k + 1] = nums[queue.peek()];
}
} return result;
}

让我们用一个具体的例子来看这个过程:

数组:[3,1,4,2]  窗口大小:2

初始状态:队伍为空

1. 数字3来了:
队伍:[3] 2. 数字1来了:
因为1比3小,直接排在3后面
队伍:[3,1]
第一个窗口的最大值是3 3. 数字4来了:
4比1大,1离开队伍
4比3大,3离开队伍
队伍:[4]
第二个窗口的最大值是4 4. 数字2来了:
2比4小,直接排在4后面
队伍:[4,2]
第三个窗口的最大值是4

为什么这样做更好?

  1. 每个数字最多只会进队一次,出队一次
  2. 我们不用每次都看窗口里的所有数字
  3. 队伍的最前面永远是当前窗口的最大值

这就像在拍马拉松照片时,不用每次都量所有人的身高,而是保持一个有序的记录,随时知道当前画面中最高的人是谁。

小结

解决滑动窗口最大值问题,关键是要想到:

  1. 我们不需要记住窗口里的所有数
  2. 只需要保持一个"从大到小"的顺序
  3. 及时把不在窗口范围内的数字删除

这样,我们就把一个看起来很复杂的问题,变成了一个简单的"排队游戏"!


作者:忍者算法
公众号:忍者算法
c2f29413-f36f-4fc1-a443-9eabbdb400bc

从生活案例理解滑动窗口最大值:一个超直观的思路讲解|LeetCode 239 滑动窗口最大值的更多相关文章

  1. 代码随想录算法训练营day12 | leetcode 239. 滑动窗口最大值 347.前 K 个高频元素

    基础知识 ArrayDeque deque = new ArrayDeque(); /* offerFirst(E e) 在数组前面添加元素,并返回是否添加成功 offerLast(E e) 在数组后 ...

  2. Leetcode 239.滑动窗口最大值

    滑动窗口最大值 给定一个数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧.你只可以看到在滑动窗口 k 内的数字.滑动窗口每次只向右移动一位. 返回滑动窗口最大值. 示例: ...

  3. LeetCode(239.滑动窗口的最大值

    题目: 给定一个数组nums,有一个大小为k的滑动窗口从数组的最左侧移动到最右侧,你只可以看到滑动窗口内的k个数字.滑动窗口每次只向右移动一位. 返回滑动窗口中的最大值. 示例: 输入: nums = ...

  4. Java实现 LeetCode 239 滑动窗口最大值

    239. 滑动窗口最大值 给定一个数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧.你只可以看到在滑动窗口内的 k 个数字.滑动窗口每次只向右移动一位. 返回滑动窗口中的最 ...

  5. leetcode 239. 滑动窗口最大值(python)

    1. 题目描述 给定一个数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧.你只可以看到在滑动窗口内的 k 个数字.滑动窗口每次只向右移动一位. 返回滑动窗口中的最大值. 示 ...

  6. 【leetcode 239. 滑动窗口最大值】解题报告

    思路:滑动窗口的思想,只要是求连续子序列或者子串问题,都可用滑动窗口的思想 方法一: vector<int> maxSlidingWindow(vector<int>& ...

  7. 代码随想录第十三天 | 150. 逆波兰表达式求值、239. 滑动窗口最大值、347.前 K 个高频元素

    第一题150. 逆波兰表达式求值 根据 逆波兰表示法,求表达式的值. 有效的算符包括 +.-.*./ .每个运算对象可以是整数,也可以是另一个逆波兰表达式. 注意 两个整数之间的除法只保留整数部分. ...

  8. 【leetcode】239. 滑动窗口最大值

    目录 题目 题解 三种解法 "单调队列"解法 新增.获取最大值 删除 代码 题目 给你一个整数数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧.你只可以 ...

  9. 【每日一题】【双端降序队列Deque】2021年12月28日-239. 滑动窗口最大值

    给你一个整数数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧.你只可以看到在滑动窗口内的 k 个数字.滑动窗口每次只向右移动一位. 返回滑动窗口中的最大值. 来源:力扣(L ...

  10. 理解SetCapture、ReleaseCapture、GetCapture(控制了消息发往哪个窗口,是理解消息的关键)

    理解SetCapture.ReleaseCapture.GetCapture 正常情况下,鼠标指针位于哪个窗口区域内,鼠标消息就自动发给哪个窗口.如果调用了SetCapture,之后无论鼠标的位置在哪 ...

随机推荐

  1. 高性能计算-openmp-图像卷积滤波算法(12)

    1. 目标:使用openmp实现图像滤波算法 给定一个输入图像,你的任务是将其划分为多个块,并使用多个进程对每个块进行滤波操作. 要求: 1.使用分段并行结构和指令section来并行执行不同的计算步 ...

  2. MySQL8.0新特性之增强版逻辑备份恢复

    前言关于MySQL库表逻辑备份恢复,我们主要有以下几种常用的工具: 1.mysqldump:MySQL原生自带的逻辑备份恢复工具,支持整个实例.单个数据库.单张表等的备份与恢复,对于1-10个G的数据 ...

  3. MongoDB学习笔记之 第1章 MongoDB的安装

    MongoDB学习笔记之 第1章 MongoDB的安装 MongoDB学习笔记之 第2章 MongoDB的增删改查 MongoDB学习笔记之 第3章 MongoDB的Java驱动 MongoDB学习笔 ...

  4. Graylog之进阶操作

    有关系统的索引,权限,pipline 参考文章: https://mp.weixin.qq.com/s/LROHPjZEJPMsS5M_a3pPFw https://blog.csdn.net/wei ...

  5. Blazor 组件库 BootstrapBlazor 中Modal组件介绍

    组件说明 Model组件是一个模态框组件,可以弹出一个对话框,适合需要定制性更大的场景. 它的样子如下: 其html代码为: <div class="modal-content&quo ...

  6. manim边做边学--曲面

    Surface类是Manim中专为创建和操控复杂的三维表面而打造的. 在实际应用中,无论是创建数学教学中的几何模型,还是模拟物理现象中的曲面变化,甚至是构建复杂的动画场景中的三维元素,Surface类 ...

  7. Jetpack Compose学习(14)——ConstraintLayout约束布局使用

    原文地址: Jetpack Compose学习(14)--ConstraintLayout约束布局使用-Stars-One的杂货小窝 本文阅读之前,需要了解ConstraintLayout的使用! 各 ...

  8. 【VMware VCF】管理 VCF 环境中组件的用户密码。

    默认情况下,VMware Cloud Foundation 使用 vCenter Single Sign-On 作为身份提供程序,并使用系统域作为其身份源,可以将基于 LDAP 和 OpenLDAP ...

  9. CVE-2023-3390 Linux 内核 UAF 漏洞分析与利用

    漏洞分析 漏洞成因是 nf_tables_newrule 在异常分支会释放 rule 和 rule 引用的匿名 set ,但是没有设置 set 的状态为 inactivate,导致批处理中后面的请求还 ...

  10. SDK连接节点失败排查思路

    https://fisco-bcos-documentation.readthedocs.io/zh_CN/latest/docs/faq/connect.html Important: 前置说明 1 ...