LeetCode 统计定界子数组的数目

6207. 统计定界子数组的数目

 以下代码来自 ,灵山茶

class Solution {
    public long countSubarrays(int[] nums, int minK, int maxK) {
        var ans = 0L;
        // i0标记越界的值
        int n = nums.length, minI = -1, maxI = -1, i0 = -1;
        for (var i = 0; i < n; ++i) {
            var x = nums[i];
            if (x == minK) minI = i; // 最小值的索引小标一直在更新
            if (x == maxK) maxI = i; // 最大值的索引下标一直在更新

            if (x < minK || x > maxK) i0 = i; // 子数组不能包含 nums[i0],他也作为其中一个边界


            // 下面这个式子表示,上方不断更新最小值下标和最大值下标,只取最小,作为左边界
            // 只有当两个都更新的时候,才会选择其中更小的一个作为新的边界开始。
            ans += Math.max(Math.min(minI, maxI) - i0, 0);
        }
        return ans;
    }
}

作者:endlesscheng
链接:https://leetcode.cn/problems/count-subarrays-with-fixed-bounds/solution/jian-ji-xie-fa-pythonjavacgo-by-endlessc-gag2/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

解答代码:上面的代码有点难看懂,大概是做了这样一件事,i0标记越界数字下标minImaxI分别标记符合目标区间最小值下标最大值下标

上面ans += Math.max(Math.min(minI, maxI) - i0, 0);这段代码,完美剔除了未形成目标区域的情况。

遍历数字形成目标区域的三种情况如下:

第一种情况,后续的数字没有破坏目标区域(1最小,5最大),后面每增加一个数字,紫色区域 * 1。这个比较好理解,如果1,3,5前面有3个2,后面又出现4个2,总情况就是(3 + 1) * (4 + 1),20种情况。

第二种情况,if (x < minK || x > maxK) i0 = i; 越界数字蓝色线)出现在了maxI的右边,目标区域被破坏。此时不能累加值。等待新的目标区域形成。

 第三种情况,更新新的目标区域。因为之前的情况都已经计算过了,可以直接舍去之前形成的区域,开始计算新的目标区域。(注意如果越界数字没有更新,还是上一个目标区域的情况,计算的时候,是需要计算蓝色线到红色矩形右边界的情况)。

感悟:大佬写的代码真好,我一直想着怎么去重,到最后也没有做好,计算机代码的编写不能总按照如人脑的习惯来,像这种累加计算各种情况的,就应该像大佬的代码一样,每新增一个值计算一次,细分来计算,这样不容易出错,时间复杂度也比额外处理去重要小。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值