牛客编程题-算法笔面试篇-BM45 滑动窗口的最大值
这个题我用了两种方法。
第一种方法:暴力法
思路:设置三个指针:i,j,k。其中,i和j分别为窗口左右端点,k负责从i移动至j。在k从i移动至j的一趟中,将窗口内第一个数字作为最大值,和窗口内其他数字一个一个比较,找出当前窗口中存在的最大值。然后i和j分别+1,表示窗口向右移动一格,然后重复k移动步骤。每次获得一个最大值便存入动态数组reuslt中。直到窗口右端点到达数组末尾。最后返回result数组

点击查看代码
public static ArrayList<Integer> maxInWindows(int[] num, int size) {
ArrayList<Integer> result = new ArrayList<>();
int i = 0, j = size-1, k = 0;
int max = 0;
if( size > num.length || num.length == 0 || size == 0)
return result;
for(; j < num.length; i++, j++){
k = i;
max = num[i];
for(; k <= j; k++){
if(num[k] > max)
max = num[k];
}
result.add(max);
}
return result;
}
方法二:双向单调队列法
思路:从方法一不难看出,当窗口向右移动的时候,窗口内最大值的左侧那些数据是无用的,一些比较是不必要的。因此,可以设置一个双向队列,将窗口内的“有效数据”装进去,然后将数组里的数字一个个按照一定规则和队列里的数字进行对比。
1.初始化:窗口指针i和j初始化为0,数组第一个数字直接push队尾。当指针j(以下简称j)右移的距离没有超过窗口大小size之前,i都保持不变。push完第一个数字后,j右移。
2.装载初始队列:将j指向的数字(以下简称j数字)和队尾元素进行比较。若j数字>队尾元素,则pop队尾元素,然后继续和下一个队尾元素进行比较,直至队列为空,此时直接将j数字push队尾。若j数字<=队尾元素,则直接push队尾,然后j++。重复该步骤直至j>窗口大小size。完毕将队首元素存入结果数组result。

3.移动窗口:这个阶段,j每右移一次,i也要跟着右移一次。并且每次窗口移动时,都要判断队首元素是否被移出窗口。当队首元素被移出窗口时,则需要同步将队首元素pop出队列。完成这一步后再将新的j数字和队尾元素进行比较,操作和第二步的比较规则一样。在每一次比较完毕、准备移动窗口前,将队首元素存入结果数组result。重复该步骤直至j移动至数组最后一个元素

总体来说,这个方法的思路就是“淘汰最老的,最新的最强的领导队列,最新的但并非最强的就按次序跟在队列末尾”
点击查看代码
public static ArrayList<Integer> maxInWindows(int[] num, int size){
int i = 0, j = 0;//i是窗口左端点,j是窗口右端点
ArrayDeque<Integer> queue = new ArrayDeque<>();
ArrayList<Integer> result = new ArrayList<>();
if(size == 0 || size > num.length || num.length == 0){
return result;
}
/**
* 初始化队列,队列元素为数组元素下标。让窗口滑动至数组第三个元素再进入循环
* 若当前元素大于等于队尾元素,则抛弃队尾元素,让当前元素和最新的队尾元素比较
* 若小于队尾元素,则直接将当前元素加入队尾
*/
while(j < size){
while(!queue.isEmpty() && num[ queue.getLast() ] < num [j]){
queue.pollLast();
}
queue.addLast(j++);
}
result.add(num[ queue.getFirst()]);
i++;
/**
* 开始第四个元素,进入循环
* 维护单调队列
*/
for(; j < num.length; i++, j++){
/**
* 如果窗口左边缘超过队列头元素,表示队列头元素已过期,需要pop
*/
if( i > queue.getFirst() )
queue.pollFirst();
while(queue.isEmpty() == false && num[ queue.getLast() ] < num[j] ){
queue.pollLast();
}
queue.addLast(j);
result.add(num[ queue.getFirst() ]);
}
return result;
}

浙公网安备 33010602011771号