本文参考自《剑指offer》一书,代码采用Java语言。html
更多:《剑指Offer》Java实现合集 java
给定一个数组和滑动窗口的大小,请找出全部滑动窗口里的最大值。例如,若是输入数组{2, 3, 4, 2, 6, 2, 5, 1}及滑动窗口的大小3,那么一共存在6个滑动窗口,它们的最大值分别为{4, 4, 6, 6, 6, 5}数组
蛮力直接在每一个滑动窗口依次比较找出最大值,时间复杂度过高。post
咱们考虑把每一个可能成为最大值的数字记录下来,就能够快速的获得最大值。测试
思路:创建一个两端开口的队列,放置全部多是最大值的数字(存放的实际上是对应的下标),且最大值位于队列开头。从头开始扫描数组,url
若是遇到的数字比队列中全部的数字都大,那么它就是最大值,其它数字不多是最大值了,将队列中的全部数字清空,放入该数字,该数字位于队列头部;spa
若是遇到的数字比队列中的全部数字都小,那么它还有可能成为以后滑动窗口的最大值,放入队列的末尾;htm
若是遇到的数字比队列中最大值小,最小值大,那么将比它小数字不可能成为最大值了,删除较小的数字,放入该数字。blog
因为滑动窗口有大小,所以,队列头部的数字若是其下标离滑动窗口末尾的距离大于窗口大小,那么也删除队列头部的数字。队列
注:队列中存放的是下标,以上讲的 队列头部的数字 均指 队列头部的下标所指向的数字。写代码时不要弄混了。
测试算例
1.功能测试(数组数字递增、递减、无序)
2.边界值测试(滑动窗口大小位0、一、大于或者等于数组长度)
3.特殊输入测试(null)
//题目:给定一个数组和滑动窗口的大小,请找出全部滑动窗口里的最大值。例如, //若是输入数组{2, 3, 4, 2, 6, 2, 5, 1}及滑动窗口的大小3,那么一共存在6个 //滑动窗口,它们的最大值分别为{4, 4, 6, 6, 6, 5}, public class MaxInSlidingWindow { public ArrayList<Integer> maxInWindows(int [] num, int size){ ArrayList<Integer> max = new ArrayList<Integer>(); if(num==null || num.length<=0 || size<=0 || size>num.length) return max; ArrayDeque<Integer> indexDeque = new ArrayDeque<Integer>(); for(int i=0;i<size-1;i++){ while(!indexDeque.isEmpty() && num[i]> num[indexDeque.getLast()]) indexDeque.removeLast(); indexDeque.addLast(i); } for(int i=size-1;i<num.length;i++){ while(!indexDeque.isEmpty() && num[i]> num[indexDeque.getLast()]) indexDeque.removeLast(); if(!indexDeque.isEmpty() && (i-indexDeque.getFirst())>=size) indexDeque.removeFirst(); indexDeque.addLast(i); max.add(num[indexDeque.getFirst()]); } return max; } }
1.本身最初想到的是只存放最大的数,没有想到能够存放全部多是最大的数,要记住。
2.ArrayDeque——双端队列,要记住。下面是一些经常使用的方法: