首页 > 试题广场 >

生成窗口最大值数组

[编程题]生成窗口最大值数组
  • 热度指数:7214 时间限制:C/C++ 2秒,其他语言4秒 空间限制:C/C++ 256M,其他语言512M
  • 算法知识视频讲解
有一个整型数组arr和一个大小为w的窗口从数组的最左边滑到最右边,窗口每次向右边滑一个位置,求每一种窗口状态下的最大值。(如果数组长度为n,窗口大小为w,则一共产生n-w+1个窗口的最大值)

输入描述:
第一行输入n和w,分别代表数组长度和窗口大小
第二行输入n个整数X_i,表示数组中的各个元素


输出描述:
输出一个长度为n-w+1的数组res,res[i]表示每一种窗口状态下的最大值
示例1

输入

8 3
4 3 5 4 3 3 6 7

输出

5 5 5 4 6 7

说明

例如,数组为[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

输出的结果为{5 5 5 4 6 7}

备注:

单调队列的应用,遍历数组,维护一个队头到队尾元素单调递减的双端队列(存下标,不存具体数值)。(1) 如果当前元素比队尾小,直接从队尾入队,否则不断将元素从队尾弹出,直到当前元素可以入队;(2) 如果当前窗口头部的元素为单调队列的头部元素,要加入此时的元素 就必须先从头部把窗口左边界的数弹出再将 从队尾加入,表示窗口向右滑动了一步。
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
import java.util.LinkedList;

public class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String[] params = br.readLine().split(" ");
        int n = Integer.parseInt(params[0]), w = Integer.parseInt(params[1]);
        params = br.readLine().split(" ");
        int[] arr = new int[n];
        for(int i = 0; i < n; i++) arr[i] = Integer.parseInt(params[i]);
        LinkedList<Integer> qmax = new LinkedList<>();
        int index = 0;
        for(int i = 0; i < n; 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) System.out.print(arr[qmax.peekFirst()] + " ");
        }
    }
}

发表于 2021-11-17 23:39:52 回复(0)
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.LinkedList;

public class Main{

    // 双端队列始终维持一个前大后小的结构,随着窗口右移,队列前面的元素会失效
    // 维护队列:如果队尾对应的元素小,弹出不要;如果队尾对应元素大,就把新的数组的下标加进来,继续维护前大后小的结构
    public static int[] getMaxWindow(int[] arr, int w) {
        if (arr == null || w < 1 || arr.length < w) {
            return null;
        }
        LinkedList<Integer> qMax = new LinkedList<>();
        int[] result = new int[arr.length - w + 1];
        int index = 0;
        for (int i = 0; i < arr.length; i++) {
            // 如果队尾对应的元素比较小,就弹出队尾,直到队尾的位置所代表的值比当前值arr[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) {
                result[index++] = arr[qMax.peekFirst()];
            }
        }
        return result;
    }

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int n;
        int w;
        String line;
        while ((line = br.readLine()) != null) {
            n = Integer.parseInt(line.split(" ")[0]);
            w = Integer.parseInt(line.split(" ")[1]);
            int[] data = new int[n];
            String[] inputHelp = br.readLine().split(" ");
            for (int i = 0; i < n; i++) {
                data[i] = Integer.parseInt(inputHelp[i]);
            }
            int[] res = getMaxWindow(data,w);
            StringBuilder sb = new StringBuilder();
            for (int i : res){
                sb.append(i).append(" ");
            }
            System.out.println(sb);
        }
    }
}

发表于 2020-04-05 13:42:01 回复(0)
玄学代码,过不过看命,时间设置不合理。
import java.util.*;

public class  Main{
    public static int[] getMaxWindows(int[]arr,int w){
        if(arr == null || w<1 || arr.length < w){
            return null;
        }
        LinkedList<Integer> qmax = new LinkedList<>();
        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) {
    Scanner in = new Scanner(System.in);
    int length = in.nextInt();
    int w = in.nextInt();
    int[] arr = new int[length];
    for(int i=0;i<length;i++){
        arr[i] = in.nextInt();
    }
    int[] res =   getMaxWindows(arr,w);
    in.close();
    for(int i=0;i<length-w+1;i++){
    System.out.print(res[i]+" ");
    }
       
    }
}


发表于 2019-08-14 22:15:08 回复(0)

问题信息

上传者:小小
难度:
4条回答 4412浏览

热门推荐

通过挑战的用户

查看代码