栈和队列——3.滑动窗口最大值

news/2024/9/24 4:24:13/

力扣题目链接

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

示例:

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

题干很简单,不考虑复杂度的话,那就是定义一个空数组,遍历一遍的过程中每次从窗口中再找到最大的数值加入空数组呗。但在考虑复杂度的情况下,你可以利用队列来完成这个题目,将数组nums中的数慢慢推进队列,按规则对数进行进出操作,这样复杂度就降低了很多。

那么到底怎么去制定进出规则呢,我们结合代码进行分析,《代码随想录》完整代码如下:

from collections import dequeclass MyQueue: #单调队列(从大到小def __init__(self):self.queue = deque() #这里需要使用deque实现单调队列,直接使用list会超时#每次弹出的时候,比较当前要弹出的数值是否等于队列出口元素的数值,如果相等则弹出。#同时pop之前判断队列当前是否为空。def pop(self, value):if self.queue and value == self.queue[0]:self.queue.popleft()#list.pop()时间复杂度为O(n),这里需要使用collections.deque()#如果push的数值大于入口元素的数值,那么就将队列后端的数值弹出,直到push的数值小于等于队列入口元素的数值为止。#这样就保持了队列里的数值是单调从大到小的了。def push(self, value):while self.queue and value > self.queue[-1]:self.queue.pop()self.queue.append(value)#查询当前队列里的最大值 直接返回队列前端也就是front就可以了。def front(self):return self.queue[0]class Solution:def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]:que = MyQueue()result = []for i in range(k): #先将前k的元素放进队列que.push(nums[i])result.append(que.front()) #result 记录前k的元素的最大值for i in range(k, len(nums)):que.pop(nums[i - k]) #滑动窗口移除最前面元素que.push(nums[i]) #滑动窗口前加入最后面的元素result.append(que.front()) #记录对应的最大值return result
from collections import deque

导入第三方库中的队列。我们继续去分析自定义的三个函数。

    def pop(self, value):if self.queue and value == self.queue[0]:self.queue.popleft()#list.pop()时间复杂度为O(n),这里需要使用collections.deque()

首先是出队列规则,队列存在,将队列第一个值推出。那直接用popleft将最左边的数推出不就行了吗?为什么还要判断要推出的值是不是等于队列最左边的值呢?这就涉及到了后面第二个函数push进队列的规则和主代码程序了,我们继续往下看。

    def push(self, value):while self.queue and value > self.queue[-1]:self.queue.pop()self.queue.append(value)

其次是进队列规则,先进行while循环,队列存在,如果新进的数大于队列中最右侧数(即上一个进队列的数),那就将最右侧数推出(直接pop,推出最左侧数才需要特意说明popleft),一直循环,直到队列中最右侧的数大于等于新进数,那就把新进数加入队列。

因为进队列的规则,所以如示例中,第一个滑动窗口为1,3,-1时,1先进入队列,3进入时根据规则将1推出,再进入-1,所以该滑动窗口中进入队列的只有3和-1。

    def front(self):return self.queue[0]

最后是找出最大值的函数,既然我们的队列是从大到小排列,那么每次滑动窗口中的最大值就是队列中的第一个数,直接return到quene[0]就行了。

接下来看主程序代码

    def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]:que = MyQueue()result = []for i in range(k): #先将前k的元素放进队列que.push(nums[i])result.append(que.front()) #result 记录前k的元素的最大值for i in range(k, len(nums)):que.pop(nums[i - k]) #滑动窗口移除最前面元素que.push(nums[i]) #滑动窗口前加入最后面的元素result.append(que.front()) #记录对应的最大值return result

定义一个空队列,一个空数组(用来储存最大值)。接着先将滑动窗口中的数推进队列,根据push定义的规则,示例中第一次滑动窗口只有3和-1进入了队列,先储存队列中的第一个数。

接着开始移动滑动窗口,首先推出滑动窗口第一个数,这里就可以解释我们上文在pop函数定义时留下的问题了,理论上滑动窗口第一个数nums[i-k]需要被推出,但类似示例中这种情况时,首次滑动窗口的1,3,-1,推出nums[i-k]=nums[0]=1,但1在push进入队列时就已经被推出了,要推出的值value不等于队列中的第一个数代表着在push过程中就已经被推出了,那我还要推出吗,那就不需要了,1,3,-1中按规则3还能参加下一次滑动窗口,因此在pop函数中定义了这一规则。

其次按规则push一个新的数,将每次滑动窗口中进入队列中的数的最大值加入result数组,最终return到result数组。


http://www.ppmy.cn/news/1505312.html

相关文章

Android ScanResults里的信息

1、无密码和有密码的scanresults 里信息是啥样的? 主要区别就是里面的capabilities 有密码的: 07-26 05:42:01.153 3355 3355 I WifiBroadcastReceiver: scanResult : SSID: Redmi_697B, BSSID: a4:39:b3:70:8c:20, capabilities: [WPA2-PSK-CCMP][RS…

微信小程序_对接腾讯实时音视频_多人会议

目录 一、开通腾讯实时音视频 1.腾讯实时音视频简介 2.创建应用 二、快速接入 1.微信小程序账号类目资格 2.跑通腾讯多人会议源码 3.发行项目 三、开发自己的业务代码 如何对接腾讯实时音视频的多人会议产品,从开通服务到对接完成,一 一讲解。 一…

C++——哈希结构

1.unordered系列关联式容器 本节主要介绍unordered_map和unordered_set两个容器&#xff0c;底层使用哈希实现的 unordered_map 1.unordered_map是储存<key,value>键值对的关联式容器&#xff0c;其允许通过key快速查找到对应的value&#xff0c;和map非常相似&#x…

Hive JOIN性能调优:从WHERE条件到子查询与分区策略的全方位探索

文章目录 前言场景说明场景一&#xff1a;JOIN前使用WHERE条件场景二&#xff1a;JOIN后使用WHERE条件结论案例总结 前言 在Hive中&#xff0c;当你执行一个包含JOIN操作的查询时&#xff0c;WHERE条件的使用时机和它对查询性能的影响是一个重要的考虑因素。WHERE条件可以在JO…

PHP如何实现登录认证和鉴权

本文由 ChatMoney团队出品 在Web开发中&#xff0c;用户认证&#xff08;Authentication&#xff09;和授权&#xff08;Authorization&#xff09;是构建安全应用程序的核心组件。用户认证是验证用户身份的过程&#xff0c;确保用户是他们声称的那个人。而授权则是确定已认证用…

【八股文】MySQL

1.char 和 varchar的区别 char是定长的&#xff0c;varchar是可变的字符串char适合存长度差不多的或者较短的&#xff0c;例如手机号&#xff0c;身份证&#xff0c;MD4加密算法。varchar用来存备注信息&#xff0c;用户昵称等不确定长度的信息。 2.Decimal、double和float的区…

MySQL——表的约束(一)主键约束

为了防止数据表中插人错误的数据&#xff0c;在 MySQL中&#xff0c;定义了一些维护数据库完整性的规则&#xff0c;表的约束。下表列举了常见的表的约束。 约束条件说明PRIMARY KEY主键约束,用于唯一标识对应的记录FOREIGN KEY外键约束NOT NULL非空约束UNIQUE唯一性约束DEFAU…

Linux中区域设置

Linux中区域设置 sudo locale-gen en_US.UTF-8 sudo update-locale LANGen_US.UTF-8如果您的系统提示 locale-gen 命令未找到&#xff0c;这可能是因为某些发行版的 Linux 系统默认没有安装这个工具 确认Linux发行版本->找到对应的系统安装对应的插件->重新执行命令 1…