题目描述
给定一个数组和滑动窗口的大小,找出所有滑动窗口里数值的最大值。例如,如果输入数组{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]}。
解法
使用双端队列解决,在java中可使用:ArrayDeque和LinkedList去解决
双端队列是一个两边均可进出的队列,在本题中,可使用队列首端作为当前窗口最大的元素,然后与数组内的元素比较,一旦到达窗口,就将第一个值移除且加入结果中(因为窗口每次只移动一格),具体实现代码如下。
import java.util.*;
public class Solution {
public ArrayList<Integer> maxInWindows(int [] num, int size)
{
if(num.length == 0||size <= 0||num.length < size){
return new ArrayList<Integer>();
}
ArrayList<Integer> result = new ArrayList<Integer>();
LinkedList<Integer> deque = new LinkedList<Integer>();
//第一个元素是窗口当前最大的元素
for(int i = 0;i < num.length;i++){
while(!deque.isEmpty() && num[deque.peekLast()] < num[i]){
deque.pollLast();//去除所有小于num[i]的元素
}
deque.addLast(i);//加入一个新元素
if(deque.peekFirst() == i - size){//清楚已经过期的元素
deque.pollFirst();
}
if(i >= size - 1){//用于第一次到达窗口
result.add(num[deque.peekFirst()]);//过期元素已被清除
}
}
return result;
}
}