题目描述
给定一个数组和滑动窗口的大小,找出所有滑动窗口里数值的最大值。例如,如果输入数组{2,3,4,2,6,2,5,1}及滑动窗口的大小3,那么一共存在6个滑动窗口,他们的最大值分别为{4,4,6,6,6,5}; 针对数组{2,3,4,2,6,2,5,1}的滑动窗口有以下6个: {[2,3,4],2,6,2,5,1}, {2,[3,4,2],6,2,5,1}, {2,3,[4,2,6],2,5,1}, {2,3,4,[2,6,2],5,1}, {2,3,4,2,[6,2,5],1}, {2,3,4,2,6,[2,5,1]}。
# -*- coding: utf-8 -*-
# @Time : 2019-10-07 15:40
# @Author : Jayce Wong
# @ProjectName : job
# @FileName : maxInWindows.py
# @Blog : http://blog.51cto.com/jayce1111
# @Github : https://github.com/SysuJayce
class Solution:
"""
滑动窗口问题一般往队列方向去想,因为滑动窗口本质上类似于一个queue。
而在求滑动窗口内的最大值的时候,也是先进先出的。
"""
def maxInWindows(self, num, size):
# 这里的特殊条件判断是因为牛客网的测试样例存在这样的corner case
if size < 1 or size > len(num):
return []
if len(num) == size:
return [max(num)]
res = [] # 用于保存各个窗口的最大值
queue = [] # 用于保存截止至当前有可能成为最大值的下标
for i in range(len(num)):
"""
1. 只要队尾对应的元素比下标i对应的元素要小,就将队尾的下标出队
2. 将当前下标入队
3. 将队头所有已经过期(不在当前窗口内)的下标出队
"""
while queue and num[queue[-1]] < num[i]:
queue.pop()
queue.append(i)
while queue and queue[0] < i - size + 1:
queue.pop(0)
# 如果已经遍历够一个窗口,那么就需要将该窗口的最大值保存起来
# queue的队头保存的是当前窗口的最大值对应的下标
if i >= size - 1:
res.append(num[queue[0]])
return res