算法-滑动窗口-Java

本文介绍了使用Java实现滑动窗口算法,特别是如何利用双端队列高效地找到窗口内的最大值和最小值,以及应用该算法解决求解数组中最大值与最小值之差小于或等于num的子数组数量问题。分析了双端队列在处理滑动窗口问题中的作用,并提供了O(N)时间复杂度的解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

滑动窗口-Java

  • 生成窗口的最大值或者最小值数组,时间复杂度:O(N)。

  • 普通解法的时间复杂度为O(N * win),也就是每次对一个窗口遍历其中的 win 个数,选出最大值,最优解可以做到 O(N)。

  • 【分析】:**准备一个双端队列,双端队列存放着数组中的下标值。**假设当前为 arr[i],则放入规则如下:

  • left 和 right 指针都只会向右移动,不会回退。

  • right 右滑,窗口加数:

    • 1)如果 queue 为空,直接把下标 i 放入 queue 中;
    • 2)如果 queue 不为空,取出当前 queue 队尾存放的下标 j。如果 arr[j] > arr[i],则直接把 i 放入队尾;
    • 3)如果 arr[j] <= arr[i],则一直从 queue 的队尾弹出下标,直到某个下标在 queue 中的对应值大于 arr[i],然后把 i 放入队尾 【为什么可以弹出,因为我永远比你晚过期,我又比你大或者和你一样大,有我在,你永远不可能最大,所以你可以滚了】
  • left 右滑,窗口减数:

    • 1)看弹出的 left 是否与队列头相等,如果相等,说明这个队列头已经不在窗口内了,所以弹出 queue 当前的队首元素 。
  • 双端队列的队头就是当前窗口最大值的下标。

public class Window {
   
   
    public int[] arr;
    private int left;
    private int right;
    private final LinkedList<Integer> queue;
    public Window(int[] arr){
   
   
        this.arr = arr;
        left = 0;
        right = 0;
        queue = new LinkedList<>();
    }

    public Integer getMax(){
   
   
        if (queue.isEmpty()){
   
   
            return null;
        }
        return arr[queue.peekFirst()];
    }

    // 往滑动窗口加数时对双端队列的操作
    public void addNumToRight(){
   
   
        if (right == arr.length){
   
   
            // right已经到达最右了,滑动窗口无法再增加数了
            return;
        }

        while (!queue.isEmpty() && arr[queue.peekLast()] <= arr[right]){
   
   
            queue.pollLast();
        }

        queue.add(right);
        right++;
    }

    // 移除双端队列最左边的值
    public void removeNumFromLeft(
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

木子津

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值