Leetcode-239-滑动窗口的最大值

题目说明

给定一个数组 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]

思路分析

这是一个典型的滑动窗口的问题。由于滑动窗口的大小k被限定在[1, nums.length],所以我们可以直接推出窗口的个数为nums.length - k + 1。

解题方法

方法一:暴力法

最简单直接的方法,就是遍历每个滑动窗口,找到每个窗口的最大值。

public class SlidingWindowMaximum {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 = i; j < i + k; j++){if( nums[j] > max ){max = nums[j];}}result[i] = max;}return result;}
}

复杂度分析

时间复杂度: O(Nk),双重循环,外层遍历数组循环N次,内层遍历窗口循环k次,所以整体就是O(N) * O(k) = O(Nk),表现较差。在leetcode上提交,会发现超出了题目要求的运行时间限制。

空间复杂度:O(N-k),输出数组用到了N-k+1的空间。

方法二:使用堆

如何优化时间复杂度呢?可以使用堆。
构建一个大顶堆(Max Heap),那么堆顶元素 heap[0] 永远是最大的。每次移动窗口的时候,我们只要维护这个堆、在里面插入删除元素,然后返回堆顶元素heap[0]就可以了。
在代码中,我们可以用一个优先队列(Priority Queue)来实现大顶堆。

public int[] maxSlidingWindow(int[] nums, int k) {int[] result = new int[nums.length - k + 1];// 用优先队列定义一个大顶堆PriorityQueue<Integer> maxHeap = new PriorityQueue<>(k, new Comparator<Integer>() {@Overridepublic int compare(Integer o1, Integer o2) {return o2 - o1; }});for (int i = 0; i < k; i++) {maxHeap.add(nums[i]);}result[0] = maxHeap.peek();// 遍历数组for(int i = 1; i <= nums.length - k; i++){maxHeap.remove(nums[i - 1]); maxHeap.add(nums[i + k - 1]); result[i] = maxHeap.peek();}return result;
}

复杂度分析

时间复杂度: O(Nlog(k)),在大小为 k 的堆中插入一个元素只需要消耗 log(k) 时间,因此这样改进后,算法的时间复杂度为O(Nlog(k))。但提交依然会超出时间限制。

空间复杂度:O(N),输出数组用到了O(N-k+1)的空间,大顶堆用了O(k)。

方法三:使用双向队列

使用堆看起来不错,但离题目要求还有差距。能否得到O(N) 的算法呢?

我们发现,窗口在滑动过程中,其实数据发生的变化很小:只有第一个元素被删除、后面又新增一个元素,中间的大量元素是不变的。也就是说,前后两个窗口中,有大量数据是 重叠 的。

[1, 3, -1,] -3, 5, 3, 6, 7
1, [3, -1, -3,] 5, 3, 6, 7
1, 3, [-1, -3, 5,] 3, 6, 7
1, 3, -1, [-3, 5,3,] 6, 7
1, 3, -1, -3,[ 5,3, 6, ]7
1, 3, -1, -3, 5,[3, 6, 7]

自然想到,其实可以使用一个 队列 来保存窗口数据:窗口每次滑动,我们就让后面的一个元素(-3)进队,并且让第一个元素(1)出队。进出队列的操作,只要耗费常数时间。

这种场景,可以使用 双向队列(也叫双端队列Dequeue),该数据结构可以从两端以常数时间压入/弹出元素。
在构建双向队列的时候,可以采用删除队尾更小元素的策略,所以,得到的其实就是一个 从大到小排序 的队列。
这样存储的元素,可以认为是遵循“更新更大”原则的。

    public int[] maxSlidingWindow(int[] nums, int k) {if (nums == null || k < 1 || nums.length < k) {return null;}// qmax 窗口最大值的更新结构// 注意双端队列里存放的是  放下标LinkedList<Integer> qmax = new LinkedList<Integer>();int[] res = new int[nums.length - k + 1];int index = 0;for (int R = 0; R < nums.length; R++) {//如果队列中有值,那么就判断进来的数是否大于之前进来的数,如果大于就把之前的数弹出while (!qmax.isEmpty() && nums[qmax.peekLast()] <= nums[R]) {qmax.pollLast();}qmax.addLast(R);//判断头部对应下标是否过期,是否该弹出了if (qmax.peekFirst() == R - k) {qmax.pollFirst();}//依次取经过每个滑动窗口的最大值,即如果还没有具备窗口规模不收集if (R >= k - 1) {res[index++] = nums[qmax.peekFirst()];}}return res;}

复杂度分析
时间复杂度:O(N),每个元素被处理两次:其索引被添加到双向队列中,以及被双向队列删除。

空间复杂度: O(N),输出数组使用了 O(N−k+1) 空间,双向队列使用了O(k)。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/16374.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

sw放样111

选择放样的草图的时候要精确选择两个草图的对应点

shell从入门到精通(22)shell正则匹配~=

文章目录 1. 基本用法2. 正则表达式捕获组(catch group)3. 匹配结果提取1. 基本用法 在 Shell 脚本中,可以使用正则表达式进行文本匹配和提取。Bash shell 支持使用 [[ … =~ … ]] 结构进行正则表达式匹配,同时还能提取匹配结果。 以下是一个简单的例子,展示了如何在 Bas…

堆(建堆算法,堆排序)

目录 一.什么是堆&#xff1f; 1.堆 2.堆的储存 二.堆结构的创建 1.头文件的声明&#xff1a; 2.向上调整 3.向下调整 4.源码&#xff1a; 三.建堆算法 1.向上建堆法 2.向下建堆法 四.堆排序 五.在文件中Top出最小的K个数 一.什么是堆&#xff1f; 1.堆 堆就…

【软考】信息系统管理工程师常见考点

目录 1、信息系统的组成2、结构化设计原则3、系统日常操作管理4、网络维护系统4要素5、能力管理的高级活动项目6、系统评价3各方面7、偶然耦合、逻辑耦合、时间耦合、过程耦合、通信耦合、顺序耦合、功能耦合8、设施和设备管理&#xff1a;电源设备管理、空调设备管理、通信应急…

JDK17新特性整理

引言 JDK 17作为Java的长期支持&#xff08;LTS&#xff09;版本&#xff0c;带来了一系列新特性和改进&#xff0c;这些变化不仅提升了Java语言的表达力&#xff0c;还增强了性能和安全性。本文将深入探讨JDK 17中的一些关键新特性&#xff0c;并提供详细的代码示例&#xff…

Docker之xfs文件系统下安装报错解决方案

一、需求说明 centos系统下安装docker最新版的时候&#xff0c;安装成功&#xff0c;启动的时候报错。报错信息“failed to start daemon: error initializing graphdriver: overlay2: the backing xfs filesystem is formatted without d_type support, which leads to incorr…

ROS添加GDB调试

文章目录 一、问题描述二、配置步骤1. debug 模式编译2. rosrun 添加GDB指令3. launch 添加GDB指令 三、GDB基本命令1. 基本2. 显示被调试文件信息3. 查看/修改内存4. 断点5. 调试运行 一、问题描述 在享受ROS带来便利的同时&#xff0c;但因每运行出现错误&#xff0c;ROS不会…

风电机组的振动控制

文章目录 0. 背景1. 原文记录 0. 背景 混塔机组的频率大概是目前业内遇见的比较普遍的通病。最近在了解风电机组振动控制的知识&#xff0c;看到一篇科普性质的文章&#xff0c;感觉不错&#xff0c;所以记录下来。想要看原文的点击这里。感谢原作者。 1. 原文记录

一文带你了解.NET能做什么?

前言 在DotNetGuide技术社区微信交流群经常看到有小伙伴问&#xff1a;.NET除了能写桌面应用和Web应用还能做什么&#xff1f;今天大姚将通过本篇文章来简单讲讲.NET能做哪些开发&#xff0c;对.NET感兴趣的小伙伴也可以自行领取文末附带的.NET相关学习资料。 .NET简单介绍 .…

多层派生时的构造函数和派生类的析构函数

一、多层派生时的构造函数 目录 一、多层派生时的构造函数 二、派生类的析构函数 析构函数的作用&#xff1a; 例&#xff1a;多级派生情况下派生类的构造函数 #include <iostream> #include<string> using namespace std; class Student { public:Student(int…

【SpeedAI科研小助手】2分钟解决知网维普AIGC检测

2分钟搞定AIGC率&#xff1f;还能降到0%&#xff1f; 使用方法&#xff1a; 打开SpeedAI科研小助手&#xff0c;将功能模式换成降AIGC率&#xff0c;后面可以一段一段自己改&#xff0c;也可以直接上传论文文件&#xff0c;SpeedAI直接帮你全文修改&#xff08;主打一个用户友…

HTML5 基本框架

HTML5基本的内容 文章目录 系列文章目录前言一、HTML5 基本框架二、具体框架结构三、知识补充总结 前言 HTML5的介绍&#xff1a; HTML5 是一种用于构建网页内容的标准化语言。它是 HTML&#xff08;超文本标记语言&#xff09;的第五个版本&#xff0c;引入了许多新的功能和特…

Jmeter-使用手册(_5.5版本)

JMeter是一个Java桌面应用程序&#xff0c;具有使用Swing图形API的图形界面。可以进行接口、性能等测试&#xff0c;也可以对任何数据库进行同样的测试&#xff0c;具有可移植性&#xff0c;可跨平台支持Windows&#xff0c;Linux&#xff0c;Mac上使用。 JMeter运行场景不仅可…

模仿高效网络进行目标检测——知识蒸馏

摘要 链接&#xff1a;https://openaccess.thecvf.com/content_cvpr_2017/papers/Li_Mimicking_Very_Efficient_CVPR_2017_paper.pdf 当前的基于卷积神经网络&#xff08;CNN&#xff09;的目标检测器需要从预训练的ImageNet分类模型中初始化&#xff0c;这通常非常耗时。在本…

Java整合ELK实现日志收集 之 Elasticsearch、Logstash、Kibana

简介 Logstash&#xff1a;用于收集并处理日志&#xff0c;将日志信息存储到Elasticsearch里面 Elasticsearch&#xff1a;用于存储收集到的日志信息 Kibana&#xff1a;通过Web端的可视化界面来查看日志&#xff08;数据可视化&#xff09; Logstash 是免费且开放的服务器端数…

promise试用

AB 序列完成 async function A() {return new Promise<void>((resolve,reject)>{setTimeout(()>{console.log(A ok);resolve()},1000)}) }async function B() {return new Promise<void>((resolve,reject)>{setTimeout(()>{console.log(B ok);resolve…

AI办公自动化:用kimi批量将word文档部分文件名保存到Excel中

文件夹中有很多个word文档&#xff0c;现在只要英文部分的文件名&#xff0c;保存到一个Excel文件中。 可以在kimi中输入提示词&#xff1a; 你是一个Python编程专家&#xff0c;要完成一个编写Python脚本的任务&#xff0c;具体步骤如下&#xff1a; 打开文件夹&#xff1a;…

目标检测YOLO实战应用案例100讲-【自动驾驶】激光雷达

目录 前言 算法原理 测距方法 发射单元 接收单元 扫描单元

数据集002:眼疾识别数据集 (含数据集下载链接)

说明 病理性近视&#xff08;Pathologic Myopia&#xff0c;PM&#xff09;的医疗类数据集&#xff0c;包含1200个受试者的眼底视网膜图片&#xff0c;训练、验证和测试数据集各400张。 说明&#xff1a; 如今近视已经成为困扰人们健康的一项全球性负担&#xff0c;在近视人…

斯坦福2024人工智能指数报告 1

《人工智能指数报告》由斯坦福大学、AI指数指导委员会及业内众多大佬Raymond Perrault、Erik Brynjolfsson 、James Manyika、Jack Clark等人员和组织合著&#xff0c;旨在追踪、整理、提炼并可视化与人工智能&#xff08;AI&#xff09;相关各类数据&#xff0c;该报告已被大多…