从生活案例理解滑动窗口最大值:一个超直观的思路讲解|LeetCode 239 滑动窗口最大值
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;
}
这个方法很直观,就像用眼睛一个一个数字比较。但是,如果数组很长,窗口很大,这样做就会很慢。
聪明的解决方案:排队游戏
现在我们来学一个更聪明的方法。想象一个游戏:
- 我们有一群小朋友排队,每个小朋友手里举着一个数字牌。
- 我们要保证队伍里的小朋友,从前到后手里的数字是从大到小的。
- 当新的小朋友要进队时,就要把队伍后面所有比他数字小的小朋友请出队。
- 队伍最前面的小朋友,就是当前窗口的最大值。
用代码来实现这个想法:
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
为什么这样做更好?
- 每个数字最多只会进队一次,出队一次
- 我们不用每次都看窗口里的所有数字
- 队伍的最前面永远是当前窗口的最大值
这就像在拍马拉松照片时,不用每次都量所有人的身高,而是保持一个有序的记录,随时知道当前画面中最高的人是谁。
小结
解决滑动窗口最大值问题,关键是要想到:
- 我们不需要记住窗口里的所有数
- 只需要保持一个"从大到小"的顺序
- 及时把不在窗口范围内的数字删除
这样,我们就把一个看起来很复杂的问题,变成了一个简单的"排队游戏"!
作者:忍者算法
公众号:忍者算法
c2f29413-f36f-4fc1-a443-9eabbdb400bc
从生活案例理解滑动窗口最大值:一个超直观的思路讲解|LeetCode 239 滑动窗口最大值的更多相关文章
- 代码随想录算法训练营day12 | leetcode 239. 滑动窗口最大值 347.前 K 个高频元素
基础知识 ArrayDeque deque = new ArrayDeque(); /* offerFirst(E e) 在数组前面添加元素,并返回是否添加成功 offerLast(E e) 在数组后 ...
- Leetcode 239.滑动窗口最大值
滑动窗口最大值 给定一个数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧.你只可以看到在滑动窗口 k 内的数字.滑动窗口每次只向右移动一位. 返回滑动窗口最大值. 示例: ...
- LeetCode(239.滑动窗口的最大值
题目: 给定一个数组nums,有一个大小为k的滑动窗口从数组的最左侧移动到最右侧,你只可以看到滑动窗口内的k个数字.滑动窗口每次只向右移动一位. 返回滑动窗口中的最大值. 示例: 输入: nums = ...
- Java实现 LeetCode 239 滑动窗口最大值
239. 滑动窗口最大值 给定一个数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧.你只可以看到在滑动窗口内的 k 个数字.滑动窗口每次只向右移动一位. 返回滑动窗口中的最 ...
- leetcode 239. 滑动窗口最大值(python)
1. 题目描述 给定一个数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧.你只可以看到在滑动窗口内的 k 个数字.滑动窗口每次只向右移动一位. 返回滑动窗口中的最大值. 示 ...
- 【leetcode 239. 滑动窗口最大值】解题报告
思路:滑动窗口的思想,只要是求连续子序列或者子串问题,都可用滑动窗口的思想 方法一: vector<int> maxSlidingWindow(vector<int>& ...
- 代码随想录第十三天 | 150. 逆波兰表达式求值、239. 滑动窗口最大值、347.前 K 个高频元素
第一题150. 逆波兰表达式求值 根据 逆波兰表示法,求表达式的值. 有效的算符包括 +.-.*./ .每个运算对象可以是整数,也可以是另一个逆波兰表达式. 注意 两个整数之间的除法只保留整数部分. ...
- 【leetcode】239. 滑动窗口最大值
目录 题目 题解 三种解法 "单调队列"解法 新增.获取最大值 删除 代码 题目 给你一个整数数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧.你只可以 ...
- 【每日一题】【双端降序队列Deque】2021年12月28日-239. 滑动窗口最大值
给你一个整数数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧.你只可以看到在滑动窗口内的 k 个数字.滑动窗口每次只向右移动一位. 返回滑动窗口中的最大值. 来源:力扣(L ...
- 理解SetCapture、ReleaseCapture、GetCapture(控制了消息发往哪个窗口,是理解消息的关键)
理解SetCapture.ReleaseCapture.GetCapture 正常情况下,鼠标指针位于哪个窗口区域内,鼠标消息就自动发给哪个窗口.如果调用了SetCapture,之后无论鼠标的位置在哪 ...
随机推荐
- golang定时器之timer+ticker
转载: https://juejin.cn/post/7327157426298011663 Timer 是一个一次性的定时器,用于在未来的某一时刻执行一次操作. 基本使用 创建 Timer 定时器的 ...
- 自动化部署之Gitlab+Jenkins+Docker
总结自动发布流程: Gitlab+Jenkins+Docker 一般部署方式: 1.外挂方式: 就是将实际的代码挂载到宿主机上,docker中提供程序运行的环境, 这样的话只需要更新对应的代码就够了 ...
- 抓包工具之Fiddler(详解)
Fiddle简介 Fiddler是最强大最好用的Web调试工具之一,它能记录所有客户端和服务器的http和https请求,允许你监视,设置断点,甚至修改输入输出数据,Fiddler包含了一个强大的基于 ...
- Java设计模式——职责链模式:解锁高效灵活的请求处理之道
嘿,各位 Java 编程大神和爱好者们!今天咱们要一同深入探索一种超厉害的设计模式--职责链模式.它就像一条神奇的"处理链",能让请求在多个对象之间有条不紊地传递,直到找到最合适的 ...
- Winform多线程持续读取PLC数据
1.Winform窗体界面 2.后台代码 点击查看代码 using Modbus.Device; using System; using System.Collections.Generic; usi ...
- tomcat部署cas6并配置自己的ssl证书
配置并安装tomcat,详见我的文章:windows安装tomcat10 安装必备的软件:(在<windows安装tomcat10>中已详细配置) apache-tomcat-10.1. ...
- vscode+evernote印象笔记+markdown写在线笔记
1. vscode安装evermonkey插件 2. vscode快捷键:Ctrl+Shift+P ,输入ever 按提示进行操作 Ever New: 创建新evernote笔记: 愉快地玩耍 点击下 ...
- 解决httpd: Could not reliably determine the server's fully qualified domain name, using 127.0.0
httpd: Could not reliably determine the server's fully qualified domain name, using 127.0.0.1 for Se ...
- mysql转换类型、类型转换、查询结果类型转换
一.问题来源 数据库一张表的主键id设为了自增,那就是int型的,但是其他表的关联字段又设置成了字符串! 而且已经开发了很久才发现问题,既然出现了问题肯定需要解决 如图 很明显id是不一样的,花了点时 ...
- NACOS MalformedInputException 无法读取中文配置问题
1. 问题描述 在windows平台中打包运行springboot jar包提示如下错误 在idea中运行正常 org.yaml.snakeyaml.error.YAMLException: java ...