25.2: 子数组达标的个数

给定一个整型数组arr,和一个整数num
某个arr中的子数组sub,如果想达标,必须满足:sub中最大值 – sub中最小值 <= num,
返回arr中达标子数组的数量

题解:

	public static int num(int[] arr, int sum) {
        if (arr == null || arr.length == 0 || sum < 0) {
            return 0;
        }

        int count = 0;
        LinkedList<Integer> maxWindow = new LinkedList<>();
        LinkedList<Integer> minWindow = new LinkedList<>();

        //[L,R]
        int R = 0;
        for (int L = 0; L < arr.length; L++) {
            //R不回退
            while (R < arr.length) {
                //维护大端双端队列
                while (!maxWindow.isEmpty() && arr[R] >= arr[maxWindow.peekLast()]) {
                    maxWindow.pollLast();
                }
                maxWindow.addLast(R);

                //维护小端双端队列
                while (!minWindow.isEmpty() && arr[R] <= arr[minWindow.peekLast()]) {
                    minWindow.pollLast();
                }
                minWindow.addLast(R);

                //进行条件判断
                if (arr[maxWindow.peekFirst()] - arr[minWindow.peekFirst()] > sum) {
                    //ATTENTION:这个地方必须退出来计算count,因为有可能出现R已经走到头但是L未走到头的情况,
                    //at this stitution 写在里面就不会计算count了。
                    break;
                } else {
                    R++;
                }
            }
            count += R - L;
            //将L位置的数字tan'chu'lai
            while (!maxWindow.isEmpty() && maxWindow.peekFirst() <= L) {
                maxWindow.pollFirst();
            }
            while (!minWindow.isEmpty() && minWindow.peekFirst() <= L) {
                minWindow.pollFirst();
            }
        }
        return count;
    }

思路:

刚开始时L,R指向0小标,R一直向后移动,直至不达标停止。

此时 [L , R)之间所有的搭配都达标。但是我计算的是以L为起点,到R结束(不包括R)的达标的个数是R-L个。

------- 即以L为开头的满足条件的子数组最长到R位置(不包括R)。

之后再让L指针向右移动一下到1下标,再计算以1位置为起点的满足条件的子数组最长到哪个地方停止,然后计算以1为头的子数组个数。

-----------------------循环往后直至L到头

注意的一点是:R是不回退的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

HackerTerry

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

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

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

打赏作者

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

抵扣说明:

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

余额充值