每日leetcode——239. 滑动窗口最大值

延寿星君
• 阅读 809

题目

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

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

输入: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


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

思路

双端队列
用一个双端队列,模拟窗口
遍历数组:

  • 队列为空,当前元素直接加入队列中
  • 队列不为空,当前元素<队尾元素,当前元素加入队列中;当前元素>=队尾元素,弹出队尾元素,当前元素加入队列中。这样保证队头元素,永远是当前窗口的最大值。
  • 队头元素超出了窗口范围,弹出队头元素

队列中加入的并不是元素的值,而是元素在数组中的下标,这么做是为了通过下标判断队头元素是否超出了窗口范围

import collections
def maxSlidingWindow(nums, k):
    n = len(nums)
    # 定义一个双端队列,模拟窗口
    q = collections.deque()
    # 数组ans保存结果
    ans = []
    
    # 第一个窗口没有完全进入数组中,单独处理
    # 【】[1,2,3...] 【[1】,2,3...] 【[1,2】,3...] [【1,2,3】,...]
    for i in range(k):
        # 当前>=队尾,删除队尾,加入当前
        while q and nums[i]>=nums[q[-1]]:
            q.pop()
        q.append(i)
    # 保存第一个窗口的最大值
    ans.append(nums[q[0]])
    
    # 第二个窗口开始,完全在数组中移动了
    for i in range(k,n):
        # 随着窗口移动,判断队头是否还在窗口范围中,不在就删除
        if q[0]<=i-k:
            q.popleft()
        
        # 当前>=队尾,删除队尾,加入当前
        while q and nums[i]>=nums[q[-1]]:
            q.pop()
        q.append(i)
        
        # 当前队头是当前窗口的最大值,保存最大值到ans
        ans.append(nums[q[0]])
    return ans
  1. 为什么要判断队头元素在不在窗口范围,窗口每次移动,队头肯定就不在窗口范围了,直接删除队头不就好了?
    队头是当前窗口的最大元素,不是最左边元素,所以要判断随着窗口个移动,队头元素还在不在窗口范围中。
  2. 为什么当前元素<队尾元素,当前元素还要加入队列。不加入可不可以,只要保持队头是当前窗口最大元素不就行了?
    [【5,3,2】,1],假设当前窗口队头是5,后面的3,2都小于5,如果3、2不加入队列中,遍历到1的时候,5超过窗口范围被删除,此时队列就是空的,那1就成了当前窗口的最大值,显然是错误的。

      加入 正确              不加入 错误
    # 遍历到2
    【5,3,2】,1         【5】,3,2,1
    # 遍历到1
     5,【3,2,1】         5,3,2,【1】
点赞
收藏
评论区
推荐文章
腾讯T2亲自讲解!Android-App的设计架构经验谈
正文我们今天将说明以下14种模式:1.滑动窗口2.二指针或迭代器3.快速和慢速指针或迭代器4.合并区间5.循环排序6.原地反转链表7.树的宽度优先搜索(TreeBFS)8.树的深度优先搜索(TreeDFS)9.TwoHeaps10.子集11.经过修改的二叉搜索12.前K个元素13.K路合并14.拓扑排序我们开始吧!1.滑动窗口滑动窗口模式
Wesley13 Wesley13
3年前
TCP滑动窗口消息堆积
线上问题:客户端不能推送数据到服务端。排查:pingip或者telnetport全是正常的,不奏效。通过wireshark抓取报文查看,发现一个奇怪现象是窗口不固定,但是整体趋势是逐渐减小,直到为0.服务端报文如下:至
Wesley13 Wesley13
3年前
Java简单实现滑动窗口
由于最近有一个统计单位时间内某key的访问次数的需求,譬如每5秒访问了redis的某key超过100次,就取出该key单独处理。这样的单位时间统计,很明显我们都知道有个边界问题,譬如5秒内100次的限制。刚好前4.99秒访问都是0,最后0.01秒来了100次,5.01秒又来了100次。也就是访问有明显的毛刺情况出现,为了弱化这个毛刺情况,我们可以采用滑动
Wesley13 Wesley13
3年前
TCP面试题之滑动窗口原理
TCP滑动窗口作用:1.提供TCP可靠性:对发送的数据进行确认2.流量控制:窗口大小随链路变化一、TCP窗口机制TCP中窗口大小是指tcp协议一次传输多少个数据。因为TCP是一个面向连接的可靠的传输协议,既然是可靠的就需要传输的数据进行确认。TCP窗口机制有两种,一种是
Stella981 Stella981
3年前
Leetcode 703. 数据流中的第K大元素
1.题目要求设计一个找到数据流中第K大元素的类(class)。注意是排序后的第K大元素,不是第K个不同的元素。你的KthLargest 类需要一个同时接收整数 k和整数数组nums 的构造器,它包含数据流中的初始元素。每次调用KthLargest.add,返回当前数据流中第K大的元素。示例:
Stella981 Stella981
3年前
Flink Join
文章目录一.简介二.窗口Join2.1翻滚窗口(TumblingWindowJoin)2.2滑动窗口Join(SlidingWindowJoin)2.3会话窗口Join(SessionWindowJo
Stella981 Stella981
3年前
LeetCode 5561. 获取生成数组中的最大值
文章目录1\.题目2\.解题1\.题目给你一个整数n。按下述规则生成一个长度为n1的数组nums:nums00nums11当2<2i<n时,nums2inumsi
Stella981 Stella981
3年前
LeetCode:283.移动零——简单
题目:283.移动零:给定一个数组nums,编写一个函数将所有0移动到数组的末尾,同时保持非零元素的相对顺序。示例:输入:0,1,0,3,12输出:1,3,12,0,0说明:1.必须在原数组上操作,不能拷贝额外的数组。2.尽量减少操作
Stella981 Stella981
3年前
Leetcode724:寻找数组的中心索引(java、python3)
寻找数组的中心索引给定一个整数类型的数组nums,请编写一个能够返回数组\\“中心索引”\\的方法。我们是这样定义数组中心索引的:数组中心索引的左侧所有元素相加的和等于右侧所有元素相加的和。如果数组不存在中心索引,那么我们应该返回1。如果数组有多个中心索引,那么我们应该返回最靠近左边的那一个。
常用限流算法详解
一、有哪些常用的限流算法1.固定窗口限流;2.滑动窗口限流;3.漏桶算法限流;4.令牌桶算法限流。二、4种限流算法介绍1.固定窗口限流举例说明:假设时间窗口大小为5s,则0到5s为第一个窗口,5到10s为第二个窗
贾蔷 贾蔷
3星期前
牛客3750题滑动窗口最大值解析:双端队列优化解法与代码详解
一、题目解读要求在一个给定的整数中,计算固定大小为k的内元素的最大值。例如,当窗口滑动时,需要实时输出每个窗口中的最大值序列。该问题考察对的理解,以及如何高效维护窗口内的元素关系。二、解题思路采用(deque)维护的巧妙解法。核心思想是:中仅存储数组下标,
延寿星君
延寿星君
Lv1
仰天大笑出门去,我辈岂是蓬蒿人。
文章
4
粉丝
0
获赞
0