说明

算法: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来存储遍历过的有效数组下标,这里有两个概念,

  1. Deque存的是索引,数组下标index;
  2. 有效的,也就是最多只能是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(滑动窗口最大值)解决方案:

  1. 两个方向思维,分块处理。
  2. 用双向链表Deque来顺序存储数据。

代码下载:
https://github.com/zgpeace/awesome-java-leetcode/blob/master/code/LeetCode/src/popular/SlidingWindowMaximum.java

算法:Sliding Window Maximum(滑动窗口最大值)相关推荐

  1. 239 Sliding Window Maximum 滑动窗口最大值

    给定一个数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧.你只可以看到在滑动窗口 k 内的数字.滑动窗口每次只向右移动一位. 例如, 给定 nums = [1,3,-1,- ...

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

    一.239. 滑动窗口最大值 from collections import dequeclass MyQueue: #单调队列(从大到小def __init__(self):self.queue = ...

  3. Java算法-滑动窗口算法(Sliding Window)(十)

    滑动窗口 滑动窗口概念不仅存在于数据链路层,也存在于传输层,两者有不同的协议,但基本原理是相近的.其中一个重要区别是,一个是针对于帧的传送,另一个是字节数据的传送. 滑动窗口(Sliding wind ...

  4. (补)算法训练Day13 | LeetCode150. 逆波兰表达式求值(栈应用);LeetCode239. 滑动窗口最大值(单调队列);LeetCode347. 前K个高频元素(小顶堆,优先级队列)

    目录 LeetCode150. 逆波兰表达式求值 1. 思路 2. 代码实现 3. 复杂度分析 4. 思考 LeetCode239. 滑动窗口最大值 1. 思路 2. 代码实现 3. 复杂度分析 4. ...

  5. 最大值_Leetcode2 | 滑动窗口最大值(Q239)

    :) Sliding Window Maximum Q 239 今天也是好心情 Problem Description ··· Difficulty··· You are given an array ...

  6. ST算法 Sliding Window algorithm template

    ST算法(Sliding Window):A easy way to slove the substring problems algorithm template to slove substrin ...

  7. 嗯,查询滑动窗口最大值的这4种方法不错....

    作者 | 王磊 来源 | Java中文社群(ID:javacn666) 转载请联系授权(微信ID:GG_Stone) 本文已收录至 Github<小白学算法>系列:https://gith ...

  8. 滑动窗口最大值的golang实现

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

  9. 你还在为查询滑动窗口最大值发愁吗?点开看最高效率解法!

    作者 | 王磊 来源 | Java中文社群(ID:javacn666) 头图 |  CSDN 下载自东方IC 本文已收录至 Github<小白学算法>系列:https://github.c ...

  10. CodeTop055 滑动窗口最大值

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

最新文章

  1. LeetCode简单题之长按键入
  2. RubyGems 库发现了后门版本的网站开发工具 bootstrap-sass
  3. CAS 与.net 集成的 “循环重定向”问题分析
  4. VTK:PolyData之InterpolateMeshOnGrid
  5. 精通spring——深入java ee开发核心技术 pdf_2019精通Spring Boot 42讲 高清pdf完整版
  6. Tengine+LUA+Nginx-GridFS+jemalloc编译安装
  7. 开挂的印度裔00后:7岁“出道”教编程,12岁成为IBM荣誉顾问
  8. [翻译] SoundManager 音频管理器
  9. 计算机网络之数据链路层协议总结
  10. 前端中常用的PS操作
  11. 基于Jsp的简单论坛(BBS)的设计与实现(附代码)
  12. 美国的知名的人工智能研究机构或者实验室
  13. 计算机存储单元ASCI,在计算机存储器中,存储英文字母\quot;A\quot;时,存储的是它的( ) A.输入码B.ASCII码C - 作业在线问答...
  14. 庖丁解牛——深入解析委托和事件
  15. GAMES101 Lec6 反走样与深度缓冲
  16. 使用gpg来加密数据
  17. MongoDB——文档操作(更新文档)
  18. No7. net-snmp 一些命令行应用程序:
  19. hw1-浅谈Dota2设计元素
  20. Bootsrap,我爱你啥子嘛?

热门文章

  1. prometheus linux下载_Prometheus笔记
  2. 机电工程系计算机网络技术,我院物联网工程专业3+1及计算机网络技术专业2+1项目正式开营...
  3. fastlane php,[iOS - 自动化] fastlane/frameit
  4. 生产级mysql双写_生产级Mysql物理全量备份-Xtrabackup
  5. 2019全球区块链杭州高峰论坛将于5月17日举办!
  6. Micropython教程之TPYBoard开发板制作电子时钟(萝卜学科编程教育)
  7. 海云捷迅让OpenStack从项目实施转为服务交付
  8. 侧滑面板(对viewGroup的自定义)
  9. ruby array 额
  10. 题目29:计算表达式