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

📅  最后修改于: 2023-12-03 15:26:09.152000             🧑  作者: Mango

数据结构 | 队列 | 问题 11

介绍

队列是一种先进先出(First-In-First-Out,FIFO)的数据结构,支持在队尾插入元素,在队首删除元素,并且可以查看队首元素。

问题 11 是说给定一个数组和一个窗口的大小,求每个窗口内的最大值。这个问题可以通过队列来解决。

解题思路
  1. 首先定义一个双端队列 deque,用来存储数组的下标(deque 中存储的下标满足数组元素非递增)。
  2. 遍历数组中的每一个元素,如果当前元素比队尾元素大,则队尾元素出队(由于队列中存储的下标满足数组元素非递增,所以队尾元素出队后的下标对应的元素一定不是这个窗口内的最大值),直到队列为空或者队列中的元素比当前元素大为止。
  3. 插入当前元素的下标到队尾。
  4. 判断队首元素是否过期(即队首元素的下标是否小于当前处理的下标减去窗口大小),如果过期,删除队首元素。
  5. 当当前处理的元素下标大于等于窗口大小时,队首元素就是这个窗口内的最大值。
代码实现
def max_in_sliding_window(nums, k):
    if not nums or k < 1:  # 特判
        return []

    deque = []  # 存储元素下标的双端队列

    # 初始化双端队列
    for i in range(k):
        while deque and nums[deque[-1]] < nums[i]:
            deque.pop()
        deque.append(i)

    res = []
    for i in range(k, len(nums)):
        res.append(nums[deque[0]])

        # 判断队首元素是否过期
        if deque and deque[0] < i - k + 1:
            deque.pop(0)

        # 插入当前元素的下标到队尾
        while deque and nums[deque[-1]] < nums[i]:
            deque.pop()
        deque.append(i)

    res.append(nums[deque[0]])  # 最后一个窗口

    return res
复杂度分析

时间复杂度:O(n),由于每个元素最多进出队列一次。

空间复杂度:O(k),双端队列的最大长度为窗口大小,即 O(k)。