64. 滑动窗口的最大值
给定一个数组和滑动窗口的大小,找出所有滑动窗口里数值的最大值。例如,如果输入数组{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]},如下图所示:
![ef33db1a8f0432dafcfc403a677a86ad.png](https://i-blog.csdnimg.cn/blog_migrate/08eea88c0cb161ac114c5954fecf7fff.jpeg)
1、思路
一个重要特点:[1, 2, 3, 4], 如果size = 2, 那么就有3个窗口。如果size = 3, 就有2个窗口,size = 4,一个窗口。(窗口数 = len(array) - size + 1)
在书上的方法比较好,但是如果不是很理解这个过程的话,不是很好理解书上所讲述内容的含义,在这里我用一种比较容易理解的方式进行描述。为了输出每个窗口中的最大值,我们使用了一个数组temp,数组temp中存放着当前窗口的最大值,和按需排列好的次大值,并且这些次大值在数组中的位置只能是位于最大之后的,数组 temp 的最大规模为 size -1。
以上面的题目为例,首先在数组temp中存储 2 为目前的最大值,之后读取原始数组中的数字 3 ,由于3 比 2 大,所以将 2 弹出,将 3 压入;然后读取原始数组中的数字 4,由于4 比 3 大,所以将 3 弹出,将 4 压入;读取原始数组中的数字 6,由于 6 比 4 大,所以将 4 弹出,将 6 压入;读取原始数组中的数字 2,由于 6 比 2 大,所以 6 不会被弹出,但是这个时候 temp 的大小小于 size - 1,所以将 2 压入(因为他是目前除了6 以外最大的元素);读取原始数组中的数字 5,由于 5 比 2 大,所以将 2 弹出,先不压入5,而是将 5 与 6 进行比较,由于 6 比 5 大,所以 6 不会被弹出,但是这个时候 temp 的大小小于 size - 1,所以将 5 压入;在读取原始数组中的数字 1 之前我们发现,如果滑动窗口移动到了包含 1 的位置,那么这个时候 6 已经是在窗口之外了,也就是说 6 是过期的,所以这个时候应该首先将 6 弹出,此时 temp 只剩下 5 ,取原始数组中的数字 1,由于 5 比 1 大,所以 5 不会被弹出,但是这个时候 temp 的大小小于 size - 1,所以将 1 压入。
经过上面的举例分析,我们已经得到在滑动窗口滑动的过程中 temp 的取值过程。但是并不是在读取第一个元素的时候就开始输出滑动窗口中的最大值,而是当整个滑动窗口都读取到的时候才输出
所以找出滑动窗口的最大值的过程,实际上就两步工作:
(1)判断当前的最大值是否过期。
(2)将读入的数字与 temp 中的元素从后向前依次比较大小,将 temp 中小于读入数字的元素都弹出;如果删除后 temp 的大小还没有达到 size - 1,那么将这个元素压入(删除后 temp 的大小有可能达到 size - 1 嘛?有可能的!因为可能经过比较发现 temp 中没有元素被弹出)。
2. 代码
![6f94a57724421ab72c5a4e24d5b1c5c3.png](https://i-blog.csdnimg.cn/blog_migrate/239f004c00cc44d63855cd3dafef5dcb.jpeg)