1-7 生成窗口最大值数组

题目描述

  • 计算生成窗口最大值数组

  • 有一个整型数组arr和一个大小为w的窗口从数组最左边滑到最右边。

  • 现在要求实现一个函数,输入整型数组arr和窗口长度w,输出一个最大值数组res记录每个窗口的最大值。
    在这里插入图片描述

解题方法1

  • 最简单粗暴的方法就是直接两层遍历,代码如下。但是时间复杂度为 n*w 显然有优化的空间。
public class Test {
    public static void main(String[] args) {
       int [] arr = {4,3,5,4,3,3,6,7};
       int [] res = fun(arr,3);
       for(int a:res){
           System.out.print(a+" ");
       }
    }
    //计算每个窗口最大值并保存到数组返回
    public static int [] fun(int [] arr,int w){
         int [] res = new int[arr.length-w+1];
         for(int i=0;i<arr.length-w+1;i++){
             res[i] = getmax(arr,i,w);
         }
         return res;
    }
    //寻找一个窗口最大值
    public static int getmax(int [] arr,int start,int w){
        int max = arr[start];
        for(int i=start+1;i<start+w;i++){
            if(arr[i]>max){
                max = arr[i];
            }
        }
        return max;
    }
}

解题方法2

  • 可以使用双端队列进行优化,队列中存放元素的下标。
  • 队头弹出过期的下标,队尾压入值更小或等的下标,弹出值更大的下标。
  • 这样可以保证队头元素指向的永远是当前窗口最大值。
  • 我们根据arr数组当前遍历位置i往前推w个元素便可以判断队头是否还在窗口范围内(是否过期)。
  • 代码如下:
public class Test {
    public static void main(String[] args) {
       int [] arr = {4,3,5,4,3,3,6,7};
       int [] res = fun(arr,2);
       for(int a:res){
           System.out.print(a+" ");
       }
    }
    //计算每个窗口最大值并保存到数组返回
    public static int [] fun(int [] arr,int w){
         int [] res = new int[arr.length-w+1];
         LinkedList<Integer> queue = new LinkedList<>();
         int index = 0; //index指向res数组的下标
         for(int i=0;i<arr.length;i++){
             //队列为空 或者 i指向元素<当前队尾  将i压入队尾
             if(queue.size()==0 || arr[i]<queue.peekLast()){
                 queue.addLast(i);
             }
             //否则 弹出当前队尾继续比较 直到当前i指向值<队尾或者队列为空 然后再将i压入队尾
             else{
                 while(queue.size()>0 && arr[i]>=arr[queue.peekLast()]){
                     queue.pollLast();
                 }
                 queue.addLast(i);
             }
             //如果当前队头过期了 就把队头出队
             if(queue.peekFirst()<(i-w+1)){
                 queue.pollFirst();
             }
             //如果当前可以构成一个窗口了 就将队头保存到数组res
             if((i-w+1)>=0){
                 res[index] = arr[queue.peekFirst()];
                 index++;
             }
         }
         return res;
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章