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

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

数据结构 | 队列 | 问题11

问题描述

给定一个整数数组 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
解题思路

本题可以通过维护一个大小为 k 的滑动窗口,每次向右滑动一个位置,在窗口内找到最大的元素作为子数组的最大值并存储起来。因为是大小为 k 的窗口,所以窗口总共会滑动 $n-k+1$ 次,每次找到窗口内的最大值需要 $O(k)$ 的时间,所以算法的时间复杂度为 $O(nk)$。

使用双端队列(deque)可以在时间复杂度为 $O(n)$ 的情况下解决本问题。我们依次遍历数组中的元素,对于当前元素 nums[i],如果队列不为空,而且队列末端元素 nums[deque[-1]] < nums[i],那么我们弹出队列末端元素,直到队列为空或末端元素不小于当前元素 nums[i]。这样就保证了队列中的元素是单调不递减的,队列队首元素就是当前窗口的最大值。当窗口向右移动时,我们需要弹出队列中已经失效(已经移出窗口)的元素,以保持队列中只有当前窗口中的元素。时间复杂度为 $O(n)$。

代码实现

python代码实现如下:

from collections import deque
from typing import List

class Solution:
    def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]:
        dq = deque() 
        res = []
        for i in range(len(nums)):
            while dq and nums[dq[-1]] < nums[i]:
                dq.pop()
            dq.append(i)
            if dq[0] == i - k:
                dq.popleft()
            if i >= k - 1:
                res.append(nums[dq[0]])
        return res

返回的结果是一个列表,包含了最大子数组的各个元素。