【题解】Leetcode双周赛80 统计得分小于K的子数组数目

博客围绕Leetcode双周赛80中的题目,即统计得分小于K的子数组数目展开。题目难度为Hard,分数定义为数组之和乘以长度。解题思路是先求前缀和以快速计算区间和,再用双指针移动右指针,计算符合条件子数组数目,同时要避免重复计算。
Round 42: 统计得分小于K的子数组数目

题目来源:Leetcode双周赛80

标签:前缀和+双指针

难度:Hard

一个数字的 分数 定义为数组之和 乘以 数组的长度。

比方说,[1, 2, 3, 4, 5] 的分数为 (1 + 2 + 3 + 4 + 5) * 5 = 75 。
给你一个正整数数组 nums 和一个整数 k ,请你返回 nums 中分数 严格小于 k 的 非空整数子数组数目。

子数组 是数组中的一个连续元素序列。

输入:nums = [2,1,4,3,5], k = 10
输出:6
解释:
有 6 个子数组的分数小于 10 :
- [2] 分数为 2 * 1 = 2 。
- [1] 分数为 1 * 1 = 1 。
- [4] 分数为 4 * 1 = 4 。
- [3] 分数为 3 * 1 = 3 。 
- [5] 分数为 5 * 1 = 5 。
- [2,1] 分数为 (2 + 1) * 2 = 6 。
注意,子数组 [1,4] 和 [4,3,5] 不符合要求,因为它们的分数分别为 10 和 36,但我们要求子数组的分数严格小于 10 。

根据分数的公式:Sum∗lenSum * lenSumlen,可以想到需要先求 前缀和 ,方便快速地计算某个区间的和。

然后我们采用双指针,不断移动双指针的右指针知道区间的 分数 大于等于 k,此时计算该区间有多少个符合条件的子数组。

注意:可能会存在重复计算的情况,因此要将重复的删除

在这里插入图片描述

class Solution {
    public long countSubarrays(int[] nums, long k) {
        int n = nums.length;
        long [] preSum = new long[n+1];
        for (int i = 1;i <= n;i++){ // 计算前缀和
            preSum[i] = preSum[i-1] + nums[i-1];
        }
        long ans = 0;
        int pre_r = -1; // 记录上一个区间的有边界,用于判断是否需要删除重复计算的的子数组
        for (int l = 1;l <= n;l++){
            int r;
            // 时间优化,不用每次都从 r = l开始判断,直接从上次的pre_r开始
            if (pre_r != -1)
                r = pre_r;
            else
                r = l;
            // 如果满足区间分数小于k,右移r
            while (r <= n && (preSum[r] - preSum[l-1]) * (long)(r - l + 1) < k){
                r += 1;
            }
            // 计算此区间的符合条件子数组个数
            ans += (long)(r - l) * (long)(r - l + 1) / 2;
            if (pre_r != -1 && l < pre_r){ // 如果有重复数组 则删除重复数组
                ans -= (long)(pre_r - l) * (long)(pre_r - l + 1) / 2;
            }
            pre_r = r; // 更新有边界
            if (r > n){
                break; // 如果r > n说明全部判断完了,直接结束
            }
        }
        return ans;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值