题目描述
给定一个数组 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 总是有效的,在输入数组不为空的情况下,1 ≤ k ≤ 输入数组的大小。
进阶:
你能在线性时间复杂度内解决此题吗?
思路:
用python自带的list实现双端队列,利用双端队列实现单调队列
用双端队列来实现单调队列(严格单调) 普通队列不能从尾部弹出元素,双端可以
单调栈和单调队列可以参考 https://endlesslethe.com/monotone-queue-and-stack-tutorial.html
此题不用单调栈的原因是不能从头部(栈底)弹出元素
新的代码,更简洁,更快了
思路:
维持队列单调性的时候,用while替换for循环
# 用双端队列来实现单调队列(严格单调) 普通队列不能从尾部弹出元素,双端可以
# 单调栈和单调队列可以参考 https://endlesslethe.com/monotone-queue-and-stack-tutorial.html
# 此题不用单调栈的原因是不能从头部(栈底)弹出元素
# from collections import deque
class Solution(object):
def maxSlidingWindow(self, nums, k):
#单调队列中放的是索引,注意比较的时候是比较对应值,不要粗心做错了
monotonicQueue = []
res = []
for i in range(len(nums)):
# 删除单调队列中比新进元素不大于的元素
# 注意是值与值比较,不要粗心搞成索引与值比较
while monotonicQueue and nums[monotonicQueue[-1]] <= nums[i]:
monotonicQueue.pop()
# 添加新元素到队尾
monotonicQueue.append(i)
# 删除窗口内过期的元素,为什么不写在for循环第一步是因为如果队列中没有元素的话就会报错了
if monotonicQueue[0] == i - k:
monotonicQueue.pop(0)
# 为了初始化时候还未到k个的时候,重复输出, 以及nums为1,2 不为k的时候也能输出数
if i >= k - 1 or i + 1 >= len(nums):
# 注意要把数值放到res里面,不是索引
res.append(nums[monotonicQueue[0]])
return res