力扣239-滑动窗口最大值

239. 滑动窗口最大值 - 力扣(LeetCode)

给你一个整数数组 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

提示:

  • 1 <= nums.length <= 105
  • -104 <= nums[i] <= 104
  • 1 <= k <= nums.length

单调队列,右边进,左边出,同时记录/维护答案

首先,为了方便记录队首离开窗口,队列中记录的应为元素的下标

怎么维护单调性?如果队列的最后一个元素,在数组中对应的值不大于当前遍历到的数组元素的值,那么就一直将队列中的元素从队尾弹出,这样就确保了队列是单调递减的(更准确地说,是队列元素在数组中的对应位置的值是单调递减的),也就是说,滑动窗口的最大值对应的下标一定是队首。例如示例一中滑动窗口第二个位置,即窗口元素为 [3, -1, 3] 时,此时下一个元素是 5,那么遍历到 5 时,发现它一直比单调队列的最后一个元素对应的值要大,所以会清空单调队列,把 5 对应的下标 4 放入队列中。可以类比为,新来了一个战斗力更强且更年轻的员工,那么就要把过去的战斗力没那么强或者一样强但更老的员工优化掉,这就是"不大于"而非"小于"的原因

那如果这个最大值移出了滑动窗口怎么办?我们只需要在每次遍历的时候记录当前滑动窗口的左端点 left,比较 q[0] 和 left 的大小,如果 q[0] < left ,那么说明这个最大值移出了窗口,直接 popleft(),也就是说只有那个最大值移出了窗口,我们才会管滑动窗口左端点的元素是否移出,如果这个元素不是最大值,那么它移出与否并不需要关心

python 复制代码
class Solution:
    def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]:
        ans = [0] * (len(nums) - k + 1)
        q = deque() # 队列

        for i, v in enumerate(nums):
            # 当队尾元素不大于新遍历到的元素的值(老员工不比新员工更强),就出队
            while q and nums[q[-1]] <= v:
                q.pop()
            q.append(i)

            # 考虑最老的员工被裁的问题,即左端点出窗口
            left = i - k + 1 # 滑动窗口的左端点
            if q[0] < left:
                # 如果实力最强的员工已经达到裁员年龄(移出滑动窗口),就弹出
                q.popleft()
            
            # 将此时滑动窗口的最大值记录到答案中
            if left >= 0:
                # 如果还没形成完整的、长为 k 的滑动窗口,就先不记录答案,这也是为什么一开始不能令 ans 为 [] 的原因
                ans[left] = nums[q[0]]

        return ans

input.txt:

复制代码
3 1 3 -1 -3 5 3 6 7

其中第一个元素表示 k,后面的元素均为 nums 元素

python 复制代码
from typing import List
from collections import deque

def maxSlidingWindow(nums: List[int], k: int) -> List[int]:
    ans = [0] * (len(nums) - k + 1)
    q = deque()

    for i, v in enumerate(nums):
        while q and nums[q[-1]] <= v:
            q.pop()
        q.append(i)

        left = i - k + 1
        if q[0] < left:
            q.popleft()
        if left >= 0:
            ans[left] = nums[q[0]]
    return ans

def main():
    with open("input.txt", "r") as f:
        data = f.read().split()
    k = int(data[0])
    nums = list(map(int, data[1:]))
    print(maxSlidingWindow(nums, k))

if __name__ == "__main__":
    main()
相关推荐
2601_96574222几秒前
全媒体运营与短视频代运营,两者有什么区别?
大数据·数据结构·人工智能·算法·ai·媒体
wordbaby1 小时前
混合检索:两全其美的艺术
人工智能·算法
彧azz1 小时前
数据结构:关于图的学习
c语言·数据结构·笔记·学习·算法
热心网友俣先生1 小时前
A题-药材的烘干问题-题意逐句翻译
算法·数学建模
2601_960356381 小时前
2026秋招运营分析师能力模型:SQL、指标体系、AIGC与业务分析
算法
hetao17338372 小时前
校内场-提高组 ZYZSC-S-Round 4
c++·算法
彧azz2 小时前
二叉搜索树学习记录
c语言·数据结构·笔记·算法
手写码匠3 小时前
DeepSeek 函数调用实战:从零搭建一个会“动手“的 AI 助手
人工智能·深度学习·算法·aigc
果壳science4 小时前
《自然本源》如何实现狭义相对论的代数化
笔记·算法·几何学
302wanger4 小时前
分享一个工作习惯:整点看即时消息
算法