📅  最后修改于: 2023-12-03 15:10:20.288000             🧑  作者: Mango
给定一个整数数组 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
返回的结果是一个列表,包含了最大子数组的各个元素。