题目描述
给定一个数组和滑动窗口的大小,找出所有滑动窗口里数值的最大值。例如,如果输入数组{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},
思路
使用一个双端队列,队列第一个位置保存当前窗口的最大值,每当窗口滑动一次
1.判断当前最大值是否超出滑动窗口范围
2.新增加的值从队尾开始比较,把所有比他小的值删除
代码
import java.util.*;
public class Solution {
public ArrayList<Integer> maxInWindows(int [] num, int size){
ArrayList<Integer> res=new ArrayList<>();
//如果数组为空或长度为0,滑动窗口长度为0或滑动窗口长度大于数组长度
if(num==null || num.length==0 || size==0 || size>num.length)
return res;
//定义一个双向队列用来保存滑动窗口中的最大值
Deque<Integer> deque=new LinkedList<>();
//初始化滑动窗口
for(int i=0;i<size;i++){
//如果队列非空且窗口元素依次与队尾元素比较,若大于队尾元素,则删除队尾元素
while(!deque.isEmpty() && num[i]>num[deque.getLast()])
deque.removeLast();
//将最大值的下标从队尾开始存储到双向队列中,保证队列首元素为当前窗口最大值下标
deque.addLast(i);
}
res.add(num[deque.getFirst()]);
//右移滑动窗口
for(int i=size;i<num.length;i++){
//判断最大值是否已经滑出滑动窗口
if(!deque.isEmpty() && deque.getFirst()<=i-size)
deque.removeFirst();
while(!deque.isEmpty() && num[i]>num[deque.getLast()])
deque.removeLast();
deque.addLast(i);
res.add(num[deque.getFirst()]);
}
return res;
}
}