滑动窗口的最大值
给定一个数组和滑动窗口的大小,找出所有滑动窗口里数值的最大值。例如,如果输入数组{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]}。
//方法一:用一个变量保存最大值所在位置,向后滑动,将新增值与最大值比较
public ArrayList<Integer> maxInWindows(int [] num, int size){
ArrayList<Integer> arr = new ArrayList<Integer>();
if(num.length <= 0 || size <= 0) return arr;
int p = -1;
for(int i = 0; i < num.length - size + 1; i++){
if( p < i){
p = max(num, i, size);
arr.add(num[p]);
}
else if( num[i+size-1] > num[p]){
p =i + size - 1;
arr.add(num[p]);
}else
arr.add(num[p]);
}
return arr;
}
private int max(int [] arr,int start,int len){
int m = start;
for(int i = 0; i < len; i++){
if(arr[start + i] >= arr[m])
m = start + i;
}
return m;
}
//方法二:用一个双端队列,队列第一个位置保存当前窗口的最大值,当窗口滑动一次
//1.判断当前最大值是否过期
//2.新增加的值从队尾开始比较,把所有比他小的值丢掉
import java.util.ArrayDeque;
public ArrayList<Integer> maxInWindows(int [] num, int size){
ArrayList<Integer> res = new ArrayList<Integer>();
if(size <= 0 || num.length == 0) return res;
ArrayDeque<Integer> q = new ArrayDeque<Integer>();
for(int i = 0; i < num.length; i++){
if(q.isEmpty())
q.add(i); //i为滑动窗口内最新加入的位置
else if(q.peekFirst() < i - size + 1)
q.pollFirst(); //目前的最大值不在滑动窗口内
while( !q.isEmpty() && num[q.peekLast()] <= num[i])
q.pollLast(); //删除队列中小于最新值的位置
q.add(i); //将当前位置加入队列,队列中位置对应值为降序排列
if( i - size + 1 >= 0)
res.add(num[q.peekFirst()]);
}
return res;
}