题目

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

返回 滑动窗口中的最大值 。

示例 1:

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

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

解释:

滑动窗口的位置                   最大值
--------------------------- -----
[1 3 -1] -3 5 3 6 7 3
1 [3 -1 -3] 5 3 6 7 3
1 3 [-1 -3 5] 3 6 7 5
1 3 -1 [-3 5 3] 6 7 5
1 3 -1 -3 [5 3 6] 7 6
1 3 -1 -3 5 [3 6 7] 7

示例 2:

输入:nums = [1], k = 1

输出:[1]

提示:

1 <= nums.length <= 105
-104 <= nums[i] <= 104
1 <= k <= nums.length

来源:力扣(LeetCode)

链接:https://leetcode.cn/problems/sliding-window-maximum

题解

三种解法

这个题可以有三个解析的方法:

  1. 暴力解法:遍历数组,在每个窗口遍历找到最大值;
  2. 对窗口内容排序。使用一个数据结构记录窗口的内容,每次滑动窗口时,删除离开窗口的元素、新增加入窗口的元素,并维护数据结构内元素的顺序。
    • 可使用大顶堆、BST记录窗口内的内容
  3. 使用单调队列

文章只对使用单调队列的解法进行讲解。

“单调队列”解法

推荐讲解视频:花花酱 LeetCode 239. Sliding Window Maximum - 刷题找工作 EP159-哔哩哔哩

新增、获取最大值

想象有这样的一个queue,queue内的数据是单调递减的。那么,我们只需要获取queue的front就能获取到最大的元素。

每次向这个queue新增元素的时候,queue中的元素在数组中的位置肯定比当前元素更靠前。所以,如果queue中已有的一些元素,它们的值小于新增的元素,则它们肯定不会成为当前窗口(及后续窗口)中的最大值。

所以我们就可以把这些元素pop掉了。

每个新增的元素都是经过如上判断及操作的话,那么这个queue就是一个单调递减的queue了。留在queue中的元素是:1.当前窗口中的最大值;2.后续窗口中可能的最大值。

删除

当窗口滑过了元素的时候,就应该删除该元素。

经过前面的分析,我们知道如果滑出窗口的元素不是queue的max value的话,那说明窗口中该元素之后肯定有更大的元素成为了max value。那么这种情况下,“滑出窗口的元素”肯定已经在这个max value的元素加入到queue的时候已经被pop了。

所以我们只需要判断max value是否等于“滑出窗口的元素”,如果等于则pop front。

代码


public int[] maxSlidingWindow(int[] nums, int k) {
if (nums.length < k) {
return null;
} int[] result = new int[nums.length - k + 1];
int resultIndex = 0; // 第一个窗口(前k个元素)
MonotonicQueue monotonicQueue = new MonotonicQueue();
for (int i = 0; i < k; i++) {
monotonicQueue.push(nums[i]);
}
result[resultIndex++] = monotonicQueue.max(); // 随后的窗口
for (int i = k; i < nums.length; i++) {
if (nums[i - k] == monotonicQueue.max()) {
monotonicQueue.pop();
}
monotonicQueue.push(nums[i]);
result[resultIndex++] = monotonicQueue.max();
} return result;
} /**
* 单调Queue,first大、last小
*/
private static class MonotonicQueue { private final Deque<Integer> deque; public MonotonicQueue() {
deque = new LinkedList<>();
} public void pop() {
deque.pollFirst();
} public void push(Integer num) {
while (!deque.isEmpty() && num > deque.getLast()) {
deque.removeLast();
}
deque.offerLast(num);
} public Integer max() {
return deque.getFirst();
} }

【leetcode】239. 滑动窗口最大值的更多相关文章

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

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

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

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

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

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

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

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

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

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

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

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

  7. leetcode全部滑动窗口题目总结C++写法(完结)

    3. 无重复字符的最长子串 A: 要找最长的无重复子串,所以用一个map保存出现过的字符,并且维持一个窗口,用le和ri指针标识.ri为当前要遍历的字符,如果ri字符在map中出现过,那么将le字符从 ...

  8. [Leetcode]双项队列解决滑动窗口最大值难题

    这道题是从优先队列的难题里面找到的一个题目.可是解法并不是优先队列,而是双项队列deque 其实只要知道思路,这一道题直接写没有太大的问题.我们看看题 给定一个数组 nums,有一个大小为 k 的滑动 ...

  9. LeetCoded第239题题解--滑动窗口最大值

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

随机推荐

  1. notification(浏览器通知)

    一.notification简介 Web Notifications是HTML5 的一个特性,目前我知道的有谷歌浏览器和windows edge对它进行了支持,用于向用户配置和显示桌面通知. 二.no ...

  2. 前端基础之CSS(1)

    1.css3的新特性有哪些 (1)CSS3选择器(基本.属性.伪类具体见下) (2)CSS3边框与圆角 圆角border-radius 属性:border-top-left-radius 左上角 bo ...

  3. 前端网络安全——前端XSS

    XSS攻击:Cross Site Scripting(跨站脚本攻击) XSS攻击原理:程序+数据=结果,如果数据中包含了一部分程序,那么结果就会执行不属于站点的程序. XSS攻击能干什么?能注入Scr ...

  4. java1.7之后的比较器特别之处

    在jdk1.7环境下使用Collectons.sort()方法: 比如:Collections.sort(list, new Comparator<Integer>()); 就可能会出现异 ...

  5. Map集合的六种遍历方式

    学习目标: 熟练掌握Map的遍历方式 例题: 需求:遍历Map集合 代码如下: package com.yy.object.test.test_collection; import java.util ...

  6. [ Skill ] 为什么 Lisp 语言如此先进

    https://www.cnblogs.com/yeungchie/ 网上看到一个应该是 2002 年的文章 译文转自:为什么Lisp语言如此先进?(译文) - 阮一峰的网络日志 原文地址:Reven ...

  7. 面向对象编程-终结篇 es6新增语法

    各位,各位,终于把js完成了一个段落了,这次的章节一过我还没确定下面要学的内容可能是vue也可能是前后端交互,但无论是哪个都挺兴奋的,因为面临着终于可以做点看得过去的大点的案例项目了,先憋住激动地情绪 ...

  8. python---导入模块和包

    导入模块和包 导入模块 import的过程中发生了哪些事情? 寻找模块 如果找到,开辟一块空间,执行这个模块 把这个模块中用到的名字都收录到开辟的空间中 创建一个变量来引用这个模块的空间 注意: 模块 ...

  9. 微信小程序,制作属于自己的Icon图标

    前言 最近在接手一个微信小程序,发现里面的图标都是使用的image组件,看起来非常别扭,加载也不太顺畅. 就想着看看微信有没有类似自带的图标库可以使用. 有是有,就是太少了,翻来翻去好像也就 8 种, ...

  10. Unity-动画状态机使用细节记录

    Unity动画控制器Animator功能非常强大,总结一些具体使用细节,在动作游戏中很实用: 1.动画烘焙 不同动画之间,可能存在角色朝向,重心高度不一致: 可以在动画Eidt界面设置RootTran ...