327. 区间和的个数 (归并排序)

LeetCode: 327. 区间和的个数

在这里插入图片描述


上篇是暴力前缀和 >> 时间复杂度 O ( n 2 ) O(n^2) O(n2)
博客指路: 327. 区间和的个数 (暴力前缀和)


归并排序解法 优化 >> 时间复杂度 O ( n l o g n ) O(nlogn) O(nlogn)

思路:

在这里插入图片描述



  1. 核心代码
  2. 合 (局部排序)


归并排序

class Solution {
    public int countRangeSum(int[] nums, int lower, int upper) {
        int len = nums.length;
        if(len == 0) return 0;
        long[] pre = new long[len + 1];
        // 必然
        pre[0] = 0;
        for (int i = 1; i < pre.length; i++) {
            pre[i] = pre[i - 1] + nums[i - 1];
        }

        int ans = divde(pre, 0, pre.length - 1, lower, upper);
        return ans;
    }

    public int divde(long[] arr, int left, int right, int lower, int upper){
        // 终止条件
        if(left == right) return 0;
        int mid = left + (right - left) / 2;

        // 分
        int n1 = divde(arr, left, mid, lower, upper);
        int n2 = divde(arr, mid + 1, right, lower, upper);
        int ans = n1 + n2;

        // 排序处理后 
        // 核心代码
        int cnt = left;
        int i = mid + 1;
        int j = mid + 1;

        while(cnt <= mid){
            
            // 找到左边界
            while(i <= right && arr[i] - arr[cnt] < lower){
                i++;
            }
            while(j <= right && arr[j] - arr[cnt] <= upper){
                j++;
            }
            ans += j - i;
            cnt++;
        }


        // 合
        long[] sorted = new long[right - left + 1];
        int a = left, b = mid + 1;
        int index = 0; 
        while(a < mid + 1 || b <= right){
            if(a > mid){
                sorted[index++] = arr[b++];
            }else if(b > right){
                sorted[index++] = arr[a++];
            }else {
                // 
                if(arr[a] > arr[b]){
                    sorted[index++] = arr[b++];
                }else {
                    // 小于等于
                    sorted[index++] = arr[a++];
                }
            }
        }
        
        // 更新原数组
        for (int k = 0; k < sorted.length; k++) {
            arr[left + k] = sorted[k];
        }

        return ans;
    }   

}






官方题解: 区间和的个数

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值