算法:Sliding Window Maximum(滑动窗口最大值)
说明
算法:Sliding Window Maximum
LeetCode地址:https://leetcode.com/problems/sliding-window-maximum/
题目:
Given an array nums, there is a sliding window of size k which is moving from the very left of the array to the very right. You can only see the k numbers in the window. Each time the sliding window moves right by one position. Return the max sliding window.
Example:
Input: nums = [1,3,-1,-3,5,3,6,7], and k = 3
Output: [3,3,5,5,6,7]
Explanation: Window position Max
--------------- -----
[1 3 -1] -3 5 3 6 7 31 [3 -1 -3] 5 3 6 7 31 3 [-1 -3 5] 3 6 7 51 3 -1 [-3 5 3] 6 7 51 3 -1 -3 [5 3 6] 7 61 3 -1 -3 5 [3 6 7] 7
Note:
You may assume k is always valid, 1 ≤ k ≤ input array’s size for non-empty array.
Follow up:
Could you solve it in linear time?
解题思路1
把数组按照个数为k分组,最后一组可能不是全部数据。以组为单位,从左到右方向,逐个计算组内遇到的最大数,记录为新的数组leftMaxArray;再从右到左方向,逐个计算组内遇到的最大数,记录为新的数组rightMaxArray.
因为从左到右方向–>是最大数,从右到左方向<–也是最大数,所以在某个位置index, k个数里面最多只能跨两个域,所以Max(leftMaxArray[index], rightMaxArray[index - k + 1])就是最大数。
可能文字不清晰,直接拿例子数据说明:
Input: nums = [1,3,-1,-3,5,3,6,7], and k = 3划分数组分块, size k=3. 最有一块个数可能小于k.
1,3,-1 | -3,5,3 | 6,7 |--> 从左到右方向, 计算分块里遇到的最大数.
leftMaxArray[] = 1,3,3 | -3,5,5 | 6,7 <-- 类似的从右到左计算分块里遇到的最大数.
rightMaxArray[] = 3,3,-1 | 5,5,3 | 7,7 现在, 滑动窗口在位置i, sliding-max(i) = max{rightMaxArray(i), leftMaxArray(i+w-1)}
sliding_max = 3, 3, 5, 5, 6, 7
执行效率:因为是2n-k+1, 所以是O(n).
代码实现1
public class SlidingWindowMaximum {public int[] maxSlidingWindow(int[] nums, int k) {if (nums == null || nums.length == 0 || k <= 0) {return new int[0];}int len = nums.length;int[] windowMaxArray = new int[len - k + 1];int[] leftMaxArray = new int[len];int[] rightMaxArray = new int[len];int rightIndex;for (int i = 0; i < len; i++) {leftMaxArray[i] = i % k == 0 ? nums[i] : Math.max(leftMaxArray[i - 1], nums[i]);rightIndex = len - i - 1;rightMaxArray[rightIndex] = (i == 0 || (rightIndex + 1) % k == 0) ? nums[rightIndex] : Math.max(rightMaxArray[rightIndex + 1], nums[rightIndex]);}for (int j = 0; j <= len - k; j++) {windowMaxArray[j] = Math.max(leftMaxArray[j + k - 1], rightMaxArray[j]);}return windowMaxArray;}public static void main(String[] args) {int[] nums = {1,3,-1,-3,5,3,6,7};int k = 3;SlidingWindowMaximum obj = new SlidingWindowMaximum();int[] windowMax = obj.maxSlidingWindow(nums, k);System.out.println("Output: " + Arrays.toString(windowMax));}}
运行结果1
Output: [3, 3, 5, 5, 6, 7]
解题思路2
用双向链表Deque来存储遍历过的有效数组下标,这里有两个概念,
- Deque存的是索引,数组下标index;
- 有效的,也就是最多只能是k个数据,已经小于当前下标i - k + 1, 的数据将要清理出局,这里用
poll()
方法,一直while循环从头开始清理。如果上一个数据小于当前i,那么也就是无效的数据,不可能在i没剔除之前成为最大数,也会被提前清理掉。
那么最大数都在Deque的最前面,所以在for循环的最后一步是存储,最大值。需要注意边界,也就是 i + 1 >= k
开始存结果数据。
nums中的数据最多只会增加一次,清理一次,也就是摊销下来总时间小于2n,时间复杂度为O(n) .
代码实现2
import java.util.ArrayDeque;
import java.util.Arrays;
import java.util.Deque;public class SlidingWindowMaximum {public int[] maxSlidingWindowWithDeque(int[] nums, int k) {if (nums == null || nums.length == 0 || k <= 0) {return new int[0];}int len = nums.length;int[] windowMax = new int[len - k + 1];int windowIndex = 0;// store indexDeque<Integer> deque = new ArrayDeque<>();for (int i = 0; i < len; i++) {// remove numbers out of range kwhile (!deque.isEmpty() && deque.peek() < i - k + 1) {deque.poll();}// remove smaller numbers in k range as they are uselesswhile (!deque.isEmpty() && nums[deque.peekLast()] < nums[i]) {deque.pollLast();}// deque contains index... r contains contentdeque.offer(i);if (i + 1 >= k) {windowMax[windowIndex++] = nums[deque.peek()];}}return windowMax;}public static void main(String[] args) {int[] nums = {1,3,-1,-3,5,3,6,7};int k = 3;SlidingWindowMaximum obj = new SlidingWindowMaximum();int[] windowMax = obj.maxSlidingWindowWithDeque(nums, k);System.out.println("Output: " + Arrays.toString(windowMax));}}
运行结果2
Output: [3, 3, 5, 5, 6, 7]
代码执行效率
Runtime: 11 ms, faster than 73.94% of Java online submissions for Sliding Window Maximum.
Memory Usage: 42.7 MB, less than 41.26% of Java online submissions for Sliding Window Maximum.
总结
Sliding Window Maximum(滑动窗口最大值)解决方案:
- 两个方向思维,分块处理。
- 用双向链表Deque来顺序存储数据。
代码下载:
https://github.com/zgpeace/awesome-java-leetcode/blob/master/code/LeetCode/src/popular/SlidingWindowMaximum.java
算法:Sliding Window Maximum(滑动窗口最大值)相关推荐
- 239 Sliding Window Maximum 滑动窗口最大值
给定一个数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧.你只可以看到在滑动窗口 k 内的数字.滑动窗口每次只向右移动一位. 例如, 给定 nums = [1,3,-1,- ...
- 代码随想录算法训练营day13 | 239. 滑动窗口最大值 | 347.前 K 个高频元素
一.239. 滑动窗口最大值 from collections import dequeclass MyQueue: #单调队列(从大到小def __init__(self):self.queue = ...
- Java算法-滑动窗口算法(Sliding Window)(十)
滑动窗口 滑动窗口概念不仅存在于数据链路层,也存在于传输层,两者有不同的协议,但基本原理是相近的.其中一个重要区别是,一个是针对于帧的传送,另一个是字节数据的传送. 滑动窗口(Sliding wind ...
- (补)算法训练Day13 | LeetCode150. 逆波兰表达式求值(栈应用);LeetCode239. 滑动窗口最大值(单调队列);LeetCode347. 前K个高频元素(小顶堆,优先级队列)
目录 LeetCode150. 逆波兰表达式求值 1. 思路 2. 代码实现 3. 复杂度分析 4. 思考 LeetCode239. 滑动窗口最大值 1. 思路 2. 代码实现 3. 复杂度分析 4. ...
- 最大值_Leetcode2 | 滑动窗口最大值(Q239)
:) Sliding Window Maximum Q 239 今天也是好心情 Problem Description ··· Difficulty··· You are given an array ...
- ST算法 Sliding Window algorithm template
ST算法(Sliding Window):A easy way to slove the substring problems algorithm template to slove substrin ...
- 嗯,查询滑动窗口最大值的这4种方法不错....
作者 | 王磊 来源 | Java中文社群(ID:javacn666) 转载请联系授权(微信ID:GG_Stone) 本文已收录至 Github<小白学算法>系列:https://gith ...
- 滑动窗口最大值的golang实现
给定一个数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧.你只可以看到在滑动窗口 k 内的数字.滑动窗口每次只向右移动一位. 返回滑动窗口最大值 输入: nums = [1 ...
- 你还在为查询滑动窗口最大值发愁吗?点开看最高效率解法!
作者 | 王磊 来源 | Java中文社群(ID:javacn666) 头图 | CSDN 下载自东方IC 本文已收录至 Github<小白学算法>系列:https://github.c ...
- CodeTop055 滑动窗口最大值
滑动窗口最大值 给你一个整数数组nums,有一个大小为k的滑动窗口从数组的最左侧移动到数组的最右侧. 你只可以看到在滑动窗口内的k个数字.滑动窗口每次只向右移动一位 返回滑动窗口中的最大值 使用双端队 ...
最新文章
- LeetCode简单题之长按键入
- RubyGems 库发现了后门版本的网站开发工具 bootstrap-sass
- CAS 与.net 集成的 “循环重定向”问题分析
- VTK:PolyData之InterpolateMeshOnGrid
- 精通spring——深入java ee开发核心技术 pdf_2019精通Spring Boot 42讲 高清pdf完整版
- Tengine+LUA+Nginx-GridFS+jemalloc编译安装
- 开挂的印度裔00后:7岁“出道”教编程,12岁成为IBM荣誉顾问
- [翻译] SoundManager 音频管理器
- 计算机网络之数据链路层协议总结
- 前端中常用的PS操作
- 基于Jsp的简单论坛(BBS)的设计与实现(附代码)
- 美国的知名的人工智能研究机构或者实验室
- 计算机存储单元ASCI,在计算机存储器中,存储英文字母\quot;A\quot;时,存储的是它的( ) A.输入码B.ASCII码C - 作业在线问答...
- 庖丁解牛——深入解析委托和事件
- GAMES101 Lec6 反走样与深度缓冲
- 使用gpg来加密数据
- MongoDB——文档操作(更新文档)
- No7. net-snmp 一些命令行应用程序:
- hw1-浅谈Dota2设计元素
- Bootsrap,我爱你啥子嘛?
热门文章
- prometheus linux下载_Prometheus笔记
- 机电工程系计算机网络技术,我院物联网工程专业3+1及计算机网络技术专业2+1项目正式开营...
- fastlane php,[iOS - 自动化] fastlane/frameit
- 生产级mysql双写_生产级Mysql物理全量备份-Xtrabackup
- 2019全球区块链杭州高峰论坛将于5月17日举办!
- Micropython教程之TPYBoard开发板制作电子时钟(萝卜学科编程教育)
- 海云捷迅让OpenStack从项目实施转为服务交付
- 侧滑面板(对viewGroup的自定义)
- ruby array 额
- 题目29:计算表达式