1、题目描述
给定一个数组和滑动窗口的大小,找出所有滑动窗口里数值的最大值。
例如,如果输入数组{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]}。
2、代码详解
我们把可能成为滑动窗口的最大值的数值下标存入一个两端开口的队列index中。
1)首先遍历输入数组,在遍历次数小于窗口长度的时候,如果index数组里面含有元素而且元素后面的下标值对应的输入数组的数如果小于当前遍历到的输入数组元素值,那么就把尾部的元素下标值不断pop出来,再压入当前输入元素对应的下标值。
2)然后再从等于滑动窗口大小的位置继续遍历输入数组。首先把index数组的头元素下标值对应输入数组值压入输出数组。同样的,如果index数组里面含有元素而且元素后面的下标值对应的输入数组的数如果小于当前遍历到的输入数组元素值,那么就把尾部的元素下标值不断pop出来,同时,如果index数组内有元素,而且当一个数字的下标与当前处理的数字的下标只差大于或等于滑动窗口的大小时,这个数字已经从窗口中滑出,可以从队列中删除了,再压入当前输入元素对应的下标值。
3)最后还需要在输出数组中append一下index手元素下标对应的输入元素值。
# -*- coding:utf-8 -*-
class Solution:
def maxInWindows(self, num, size):
if not num or size <= 0:
return []
deque = [] # 最终结果,每个窗口中的最大数
if len(num) >= size:
index = [] # 存放可能为最大值数的下标,两端开口的队列
# 遍历第一个窗口
for i in range(size):
while len(index) > 0 and num[i] >= num[index[-1]]:
index.pop() # 弹出最后一个值(尾部删除)
index.append(i)
# 遍历后续窗口
for i in range(size, len(num)):
deque.append(num[index[0]]) # 加入index中队头,滑动窗口的最大值总是位于队列的头部
while len(index) > 0 and num[i] >= num[index[-1]]:
index.pop() # 尾部删除
if len(index) > 0 and index[0] <= i - size:
index.pop(0) # 当头部数字从窗口中滑出(头部删除)
index.append(i) # 最后加入的数坐标一定加入
# print(index)
deque.append(num[index[0]]) # 加入index中队头,因为非队头的数则是后来加入的数,若窗口继续滑动此数有可能最大
return deque
num = [2, 3, 4, 2, 6, 2, 5, 1]
size = 4
s = Solution()
print(s.maxInWindows(num, size))