题目:有一个整形数组arr和一个大小为window的窗口从数组的最左边滑到最右边,窗口每次向右边,窗口每次向右边滑一个位置。例如,数组为[4,3,5,4,3,3,6,7],窗口大小window=3时;
1) [4 3 5] 4 3 3 6 7 窗口最大值为5
2) 4 [3 5 4] 3 3 6 7 窗口最大值为5
3) 4 3 [5 4 3] 3 6 7 窗口最大值为5
4) 4 3 5 [4 3 3] 6 7 窗口最大值为4
5) 4 3 5 4 [3 3 6] 7 窗口最大值为6
6) 4 3 5 4 3 [3 6 7] 窗口最大值为7
请将窗口的最大值按顺序输出。
该题使用双端队列解决,队列中始终维持着从大到小的数所在的下标。处理下一个数字的时候,比当前数字小的所有下标都从队列尾弹出去,因为这些数字不可能成为窗口的最大的数了。头部失效的弹出去
该题目使用的双端队列是这样一种队列:队头部可以弹出(头部失效的时候);队尾部可以弹出(当前情况下存储这个值没有意义,它不可能是我们感兴趣的输出),队尾也可以插入(当前值插入队尾)
package niuke07;
import java.util.LinkedList;
public class DoublePointQueue {
public static int []a = {4,3,5,4,3,3,6,7};
public static int window = 3;//窗口大小
public static void main(String[] args) {
doublePoint();
}
public static void doublePoint(){
if(a==null ||a.length -window<0 ){
return;
}
int []res = new int[a.length - window+1];//保存按顺序输出的结果
int index = 0;
LinkedList<Integer> list = new LinkedList<Integer>();
for(int i=0;i<a.length;i++){
while(!list.isEmpty() && a[list.peekLast()] < a[i]){
list.pollLast();//比当前数字小的所有下标都弹出去
}
list.addLast(i);//当前数字下标插入队尾
if(i - list.peekFirst() >= window){
list.pollFirst();//头部失效,弹出去
}
if(i >= window-1){
res[index++] = a[list.peekFirst()];//这时候的头部下标对应的数字就是最大值,保存下来
}
}
for(int i=0;i<res.length;i++){
System.out.print(res[i]+" ");
}
System.out.println();
}
}