要求:
有一个整数型数组arr和一个大小为w的窗口,窗口从最左边滑到最右边,每次挪动一位,求在窗口为w大小里面最大值排列。
例如,数组为[4,3,5,4,3,3,6,7], 窗口大小为3时:
[4 3 5] 4 3 3 6 7 窗口最大值为5
4 [3 5 4] 3 3 6 7 窗口最大值为5
4 3 [5 4 3] 3 6 7 窗口最大值为5
4 3 5 [4 3 3] 6 7 窗口最大值为4
4 3 5 4 [3 3 6] 7 窗口最大值为6
4 3 5 4 3 [3 6 7] 窗口最大值为7
实现一个函数,输入为整数型arr数组,窗口大小为w,输出为一个长度为arr.length - w + 1的数组res,res[i]表示每一次窗口的最大值。
思考:
普通的比较法,时间复杂度O(N*w)的解法太费时,用另外一种解法。
假设遍历到arr[i],qmax队列为存放到数组arr的下标:
1.如果qmax为空,则将下标i放到qmax中;
2.如果qmax不为空,取出qmax队尾的值记为j;
3.如果arr[i] => arr[j],则弹出qmax[j];
4.如果arr[i] < arr[j],则将i加入到qmax里面去,若i=>w-1,则res写入arr[qmax的队头];若小于则不写入。
弹出规则为:
当qmax队头下标等于i - w 说明当前qmax对头的下标已经过期了,弹出当前队头。
实验代码:
<pre name="code" class="java">package algorithm_7;
import java.util.Arrays;
import java.util.LinkedList;
public class algorithm_7 {
public static int[] getMaxWindow(int[] arr ,int w){
if(arr == null || w < 1 || arr.length<w ){
return null;
}
LinkedList<Integer> qmax = new LinkedList<Integer>();
int[] res = new int [arr.length -w + 1];
int index = 0;
for(int i = 0; i < arr.length; i++){
while(!qmax.isEmpty() && arr[qmax.peekLast()] <= arr[i]){
qmax.pollLast();
}
qmax.addLast(i);
if(qmax.peekFirst() == i - w){
qmax.pollFirst();
}
if(i >= w - 1){
res[index++] = arr[qmax.peekFirst()];
}
}
return res;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
int[] arr_test = {4,3,5,4,3,3,6,7};
int w_test = 3;
System.out.println("result = "+Arrays.toString(getMaxWindow(arr_test,w_test)));
}
}
实验结果:
result = [5, 5, 5, 4, 6, 7]