题目
给定一个数组 nums 和滑动窗口的大小 k,请找出所有滑动窗口里的最大值。
示例:
输入: nums = [1,3,-1,-3,5,3,6,7], 和 k = 3
输出: [3,3,5,5,6,7]
思路
queue是一个双端队列,队列的头部始终保存每一步的最大值;res保存所有滑动窗口的最大值。
开始遍历nums数组,一共包含两个过程:
当窗口里的数字小于等于k个时,存入一个数字,在存入一个数字之前,首先判断队列尾部的数字是否小于待存入的数字,如果已有的数字小于待存入的数字,那么这些数字已经不可能是滑动窗口的最大值,将它们从队列中删除。
当窗口里的数字大于k个时,已经能形成窗口。队列里的操作和第一个过程一样,只是增加了一个判断,当队列头部的元素从窗口中滑出时,那么滑出的数字也需要从队列的头部中删除。
两个过程不能合并的原因是,第一个过程因为还没有形成窗口,所以res列表的值不会更新。而第二个过程的每一次循环都需要更新res的值。
代码
class Solution:
def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]:
if not nums or k==0: return []
queue = collections.deque()
res = []
for i in range(k):
while queue and nums[i]>queue[-1]:
queue.pop()
queue.append(nums[i])
res.append(queue[0])
for i in range(k,len(nums)):
if queue[0]==nums[i-k]:
queue.popleft()
while queue and nums[i]>queue[-1]:
queue.pop()
queue.append(nums[i])
res.append(queue[0])
return res
复杂度
时间复杂度 O(n)
空间复杂度 O(k)
补充
根据 队列的最大值,写出来的代码。
class Solution:
def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]:
stack1 = [] ## 保存滑动窗口里的值
stack2 = [] ## 单调队列,队列头部始终是当前滑动窗口的最大值
res = [] ## 滑动窗口的最大值列表
if not nums or k<1: return []
for num in nums[:k]:
stack1.append(num)
while stack2 and num>=stack2[-1]:
stack2.pop()
stack2.append(num)
res.append(stack2[0])
for num in nums[k:]:
# 删除队列的头部元素
if stack1[0]==stack2[0]:
stack2.pop(0)
stack1.pop(0)
# 添加新元素
stack1.append(num)
while stack2 and num>stack2[-1]:
stack2.pop()
stack2.append(num)
# 保存当前最大值
res.append(stack2[0])
return res