单调队列
- 队列中位于队首的元素是当前队列中的最大值
- 每一次滑动窗口的时候不断更新当前队列中的队首元素
思路:
- 初始化一个队列,大小为k,队列头部始终存放当前窗口中的最大元素
- 当入队列的元素值大于队列中的元素,就从队尾开始pop元素,保证队列元素为单调排列
- 当入队列的元素值小于等于队首的元素,则直接入队列
- 返回当前队列的队首元素
- 题目描述
给定一个数组 nums 和滑动窗口的大小 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 ≤ nums.length。
# 单调队列
# 1. 初始化一个队列,大小为k,队列头部始终存放当前窗口中的最大元素
# 2. 当入队列的元素值大于队列中的元素,就将队列的元素全部pop
# 3. 当入队列的元素值小于等于队首的元素,则直接入队列
# 4. 返回当前队列的队首元素
from collections import deque
class Solution:
def maxSlidingWindow(self, nums, k):
# 初始化一个队列,大小为窗口大小
self.Monotone_que = deque() # 此处用列表容易出现超时
# 初始化滑动窗口
for i in range(k):
self.push_element(self.Monotone_que,nums[i])
res = []
res.append(self.Monotone_que[0])
# 遍历剩余元素
for j in range(k,len(nums)):
self.pop_element(self.Monotone_que,nums[j-k])
self.push_element(self.Monotone_que,nums[j])
res.append(self.Monotone_que[0])
return res
def pop_element(self,que,value):
# 当要删除的值等于队首元素时,才进行弹出操作 // 由于此时是单调队列,队列中的元素呈递减排列
# 如果弹出的元素值小于队首元素时,在push的时候就已经弹出,此时不用做处理
if que and value == que[0]:
que.popleft()
def push_element(self,que,value):
# 当队列不为空,切队列末尾的元素小于需要插入的元素时,就将队列末尾的元素弹出,保证队列始终呈单调递减排列
# 切队首元素为队列中的最大值
while que and que[-1] < value:
que.pop()
que.append(value)