暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

数据结构和算法【6】窗口最大值数组

皮皮克克 2023-06-13
74

点击关注公众号,干货第一时间送达



各位,请听题:


解题:

用双端队列!

队列 queue 保持递减序,则队头就是最大值,队尾就是最小值。

我们再控制住队列长度符合窗口值w大小,即可取出移动过程中每个窗口的最大值。


1,程序执行过程

遍历数组 arr,queue中存放arr数组下标。

  1. 如果 queue为空,则当前遍历i,直接入队尾;

  2. 如果 queue队尾对应数组值 arr[queue.peekLast] 小于当前遍历i的数组值arr[i]

    则弹出队尾,直到队尾对应数组值大于 arr[i];

  3. 然后 i 加入队尾即可

  4. 如果队头值等于 i-w,则表示窗口移动过了,需要移除队头了。


2,流程如下图

依次类推,直到数组末尾。


3,完整代码

public class CodingDemo {

    public static int[] getMaxWindowArr(int[] arr, int w){
        if (arr == null || arr.length < w || w < 1){
            return null;
        }

        //1,创建双端队列
        LinkedList<Integer> queue = new LinkedList<Integer>();

        //2,创建结果数组, 长度等于 arr.length-w+1,
        //因为生成了 arr.length-w+1 个窗口
        int[] res = new int[arr.length - w + 1];
        int index = 0;

        //3,开始遍历数组
        for (int i = 0; i < arr.length; i++) {

            //3.1 如果队尾对应值小于当前遍历值,则弹出队尾,直到队尾对应数组值大于当前值
            while (!queue.isEmpty() && arr[queue.peekLast()] <= arr[i]){
                queue.pollLast();
            }

            //3.2 加入当前 i
            queue.addLast(i);

            if (queue.peekFirst() == i-w){
                queue.pollFirst();//窗口过期了,需要移除队头
            }

            //3.3 因为i从0开始,除了需要等待第一个窗口生成,
            //后面每移动一步,都会有窗口,不需要等待
            if (i+1 >= w){
                res[index++] = arr[queue.peekFirst()];//记录此窗口最大值
            }
        }
        return res;
    }

    public static void main(String[] args) {
        int[] arr = {4,3,5,4,3,3,6,7};
        System.out.println(Arrays.toString(getMaxWindowArr(arr, 3)));
    }
}


输出:

D:\java\bin\java.exe
[555467]




结束语:
Ok,到此为止,就是本篇文章的全部内容了。
该文章主要讲了 数据结构和算法: 窗口最大值数组。
如果各位有不懂的地方,欢迎发消息给小编,小编会进行详细地解答。
最后,请屏幕前的各位小可爱,动动你们的小手,给小编一个“在看”吧!

文章转载自皮皮克克,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论