Leetcode算法题【困难】239.滑动窗口最大值

一.原题如下:在这里插入图片描述

二.滑动窗口是什么?

处理数组问题或字符串问题的算法技巧;
核心思想是维护一个窗口,窗口左右边界根据条件动态调整,窗口大小可以固定也可以可变

三.滑动窗口在Java中的应用场景有哪些?

  • SpringCloud Gateway 或 SpringCloud Sentinel:限流与熔断
  • SpirngCloud Micrometer 或 Prometheus:实时数据统计,比如QPS统计、错误率统计、响应时间等
  • Spring Cache 或 Redis:缓存淘汰策略
  • SpringCloud Stream 或 Kafka:消息队列中的消费速率控制
  • 分布式系统:优化一致性哈希问题

四.解题思路

使用单调队列(递减),实现滑动窗口的最大值获取;
先构造单调队列的数据结构,成员变量使用LinkedList,方法包含push(),pop(),max()这三个函数,

方法描述请看如下:
具体步骤请查看每个关键函数的代码注释

public class MonotonicQueue {
    private final LinkedList<Integer> list = new LinkedList<>();

    /**
     * 判断列表不为空 & 链表的最新值小于n,则弹出这个最新值
     */
    public void push(int n) {
        while (!list.isEmpty() && list.getLast() < n) {
            list.pollLast();
        }

        list.addLast(n);
    }

    /**
     * 弹出最旧的值,但是要先判断这个旧值是否已经被弹出了(比如push方法中已被弹出),否则不做处理
     */
    public void pop(int n) {
        if (n == list.getFirst()) {
            list.pollFirst();
        }
    }

    /**
     * 获取最旧的值(即队列头值),就是最大的值
     */
    public int max() {
        return list.getFirst();
    }
}

五.完整题解

具体步骤请查看每个关键步骤的代码注释

    public static int[] maxSlidingWindow(int[] nums, int k) {
        // 定义返回结果
        List<Integer> res = new ArrayList<>();
        // 定义单调队列
        MonotonicQueue queue = new MonotonicQueue();

        for (int i = 0; i < nums.length; i++) {
            // 先将k-1个窗口填满到单调队列
            if (i < k - 1) {
                queue.push(nums[i]);
            } else {
                // 推入窗口,此时当前窗口已满
                queue.push(nums[i]);

                // 获取当前窗口最大值,并加入到结果列表
                int max = queue.max();
                res.add(max);

                // 删除当前窗口最旧的值,保证后续窗口还有余坐
                queue.pop(nums[i - k + 1]);
            }
        }

        // 将列表转换为数组,并返回
        int[] arrRes = new int[res.size()];
        for (int i = 0; i < res.size(); i++) {
            arrRes[i] = res.get(i);
        }
        return arrRes;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值