思路(来自剑指offer):扫描一遍数组,使用双向队列,队列中存储元素下标。
(1)从队头开始检测,移除队列中所有符合以下条件的下标:队头下标与当前元素下标之差大于等于窗口大小;
(2)从队尾开始检测,移除队列中所有符合以下条件的下标:队尾下标对应元素小于当前元素;
(3)将当前元素队尾入队;
(4)当前窗口对应的最大值为队头下标对应的元素。
public static ArrayList<Integer> maxInWindows(int [] num, int size)
{
ArrayList<Integer> answer=new ArrayList<>();
if(num==null||num.length==0||size>num.length||size<=0) return answer;
//双向队列
LinkedList<Integer> queue=new LinkedList<>();
for(int i=0,length=num.length;i<length;i++){
//队列为空,直接加入
if(queue.isEmpty()) {
queue.addFirst(i);
}
//队列不为空,从队头移除超出窗口的下标,从队尾移除不可能成为最大值的下标,将当前下标入队
else{
while(!queue.isEmpty()&&(i-queue.peek())>=size){
queue.removeFirst();
}
while(!queue.isEmpty()&&num[i]>=num[queue.getLast()]){
queue.removeLast();
}
queue.addLast(i);
}
//当前最大值
if(i+1>=size){
answer.add(num[queue.peek()]);
}
}
return answer;
}