📜  数据结构 |队列 |问题 11(1)

📅  最后修改于: 2023-12-03 14:54:56.422000             🧑  作者: Mango

数据结构 | 队列 | 问题 11

介绍

队列是一种抽象数据类型,它实现了先进先出(FIFO)的数据结构,即在队列中添加一个元素时,它将被添加到队列的尾部,而在弹出元素时,它将从队列的头部被弹出。这种数据结构是非常常见的,例如在操作系统中就经常使用队列来管理进程的执行。问题 11 是一个关于队列的经典问题,也是一道面试题常见的问题。

问题描述

问题 11 是这样的:有一个整数数组 nums 和一个大小为 k 的滑动窗口,请找出其中所有滑动窗口里的最大值。

例如,给定 nums = [1,3,-1,-3,5,3,6,7],以及 k = 3。

滑动窗口的位置 | 最大值 --- | --- [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

你需要按顺序返回滑动窗口中每个位置的最大值。

解法一

众所周知,队列在滑动窗口问题中是非常实用的,因为它能够在保持数据先进先出的同时,还能够维护一个单调递减的序列,非常适合找到窗口中的最大值。我们用双端队列来实现这个想法。

代码实现
from collections import deque

class Solution:
    def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]:
        if not nums:
            return []
        if k == 1:
            return nums

        dq = deque()
        res = []

        for i, num in enumerate(nums):
            # 弹出队尾元素,保证队列中只有k个元素
            while dq and nums[dq[-1]] < num:
                dq.pop()
            dq.append(i)

            # 弹出队头元素,保证队列中只有k个元素
            while dq and i - dq[0] >= k:
                dq.popleft()

            # 当i >= k - 1 时才开始添加元素进入res列表
            if i >= k - 1:
                res.append(nums[dq[0]])

        return res
复杂度分析

时间复杂度:O(N),其中 N 是数组 nums 的长度。每个元素都最多被插入和弹出队列一次。

空间复杂度:O(k),与队列的大小相关。

总结

问题 11 是一个关于队列的经典问题,通过维护一个单调递减的队列,我们可以在 O(N) 的时间内解决这个问题。同时,这也是一个很好的面试题,既考察了对滑动窗口的理解,又考察了对队列的掌握程度。