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. PbRL | Christiano 2017 年的开山之作,以及 Preference PPO / PrefPPO

    PrefPPO 首次(?)出现在 PEBBLE,作为 pebble 的一个 baseline,是用 PPO 复现 Christiano et al. (2017) 的 PbRL 算法. For eva ...

  2. npm : 无法加载文件 D:\Program Files\nodejs\npm.ps1,因为在此系统上禁止运行脚本

    升级node和npm之后,npm run dev 启动一个Vue项目,报错如下: npm : 无法加载文件 D:\Program Files\nodejs\npm.ps1,因为在此系统上禁止运行脚本. ...

  3. java——棋牌类游戏五子棋(singlewzq1.0)之一

    这是本人最近一段时间写的五子棋的java代码,大体框架都实现了,一些细节还需要优化. package basegame; import java.awt.Color; import java.awt. ...

  4. 终端工具之Tabby

    我工作中用的最多的工具之一就是「终端连接工具」了,因为经常和 Linux 服务器打交道,经常在上面跑代码.排查系统问题等等. Windows 系统最常用的就是 Xshell 这款终端工具了,但是它只能 ...

  5. php-fpm常见错误

    1. WARNING: Nothing matches the include pattern '/usr/local/php7/etc/php-fpm.d/*.conf' # cd /usr/loc ...

  6. 使用SharpCompress压缩,tar.gz

    之前我们介绍了如何用SharpZipLib来打.tar.gz压缩包. 但是这个压缩软件有两个问题,一是代码比较多,压缩起来没有那么方便:二是压缩的.tar.gz在linux上解压时会有警告,需要跳过这 ...

  7. SharpZipLib解压.tar.gz

    上一篇文章我们说了如何用SharpZipLib来压缩.tar.gz,这篇文章我们来看看如何解压. 直接上代码: using ICSharpCode.SharpZipLib.GZip; using IC ...

  8. nrm安装后无法使用

    前情 在使用node.js的过程中,经常会时不是遇到有些包下载安装慢或者失败,有时可以尝试切换源来解决这类问题 坑 通过npm install nrm -g安装完nrm后运行nrm一直报错 Why? ...

  9. CVE-2023-31436 数组越界漏洞

    CVE-2023-31436 数组越界漏洞 drawio: CVE-2023-31436.drawio ‍ 漏洞分析 在 qfq_change_class 里面如果用户态没有提供 TCA_QFQ_LM ...

  10. 鸿蒙UI布局实战 —— 个人中心页面开发

    1.前言 接下里我们将开启"鸿蒙UI布局系列"的学习,第一站:学习线性布局(Row/Column)+ 弹性布局(Flex) 在展开学习前,先上一个实战demo--开发一个个人中心页 ...