Leetcode 327. 区间和的个数

Leetcode 327. 区间和的个数

思路解析

在这里插入图片描述
在这里插入图片描述

自测版源码

package com.bigdata.javabasic.leetcode.sort;

public class CountOfRangeSum {
    
    
    public static int countSUMOfSubArrInRange(int[] arr, int lower, int upper){
    
    
        long currentTime = System.currentTimeMillis();
        
        if(arr == null || lower > upper) return 0;
        //calculate preSum[]
        long[] preSum = new long[arr.length];
        preSum[0] = arr[0];
        for(int i = 1; i < arr.length; i++){
    
    
            preSum[i] = preSum[i - 1] + arr[i];
        }
        //! recursive entry
        int count = countPreSumInRange(preSum, 0, preSum.length - 1, lower, upper);

        System.out.println(System.currentTimeMillis() - currentTime);
        return count;
    
    }

    public static int countPreSumInRange(long[] preSum, int L, int R, int lower, int upper){
    
    
        //!check sum of arr[0:R] (preSum[R]) isInRange, true then 1, false then 0
        if(L == R) return preSum[L] <= upper && preSum[L] >= lower ? 1 : 0;

        //check sum of arr[preSumL+1:R] isInRange
        //recursive
        int mid = L + ((R-L)>>1);
        return countPreSumInRange(preSum, L, mid, lower, upper)
                + countPreSumInRange(preSum, mid+1, R, lower, upper)
                + merge(preSum, L, R, lower, upper);

    }

    public static int merge(long[] preSum, int L, int R, int lower, int upper){
    
            
        int count = 0;
        int preSumL = L;
        int preSumR = L;
        int mid = L + ((R-L)>>1);
        //calculate count of subArr in range
        for(int i = mid + 1; i <= R; i++){
    
      //! i from (mid + 1) to R
            //!each preSum[i] has a new range for preSum[preSumRange]
            long min = preSum[i] - upper;
            long max = preSum[i] - lower;
            //! <= max, then move preSumR
            while(preSumR <= mid && preSum[preSumR] <= max) preSumR++;
            //! <min, then move preSumL
            while(preSumL <= mid && preSum[preSumL] < min) preSumL++;
            count += preSumR - preSumL;
        }

        //merge preSum[]!
        long[] help = new long[R-L+1];
        int id = 0;
        int h1 = L;
        int h2 = mid + 1;
        while(h1 <= mid && h2 <= R) 
          help[id++] = preSum[h1] < preSum[h2] ? preSum[h1++] : preSum[h2++];
        while(h1 <= mid) help[id++] = preSum[h1++];
        while(h2 <= R) help[id++] = preSum[h2++];
        for(int i = 0; i < help.length; i++) preSum[L+i] = help[i];
        
        return count;
    }
    

    public static int comparator(int[] arr, int lower, int upper){
    
    
        long currentTime = System.currentTimeMillis();
        
        if(arr == null) return 0;
        int count = 0;
        
        for(int i = 0; i < arr.length; i++){
    
    
            int sum = 0;
            for(int j = i; j < arr.length; j++){
    
    
                sum += arr[j];
                if(sum > upper) continue;  //!
                if(lower <= sum) count++;
            }
        }

        System.out.println(System.currentTimeMillis() - currentTime);
        return count;
    }

    public static void main(String[] args){
    
    
        int testTime = 500;
		int maxSize = 5000;
		int maxValue = 100;
		System.out.println("test begin!");
        for(int i = 0; i < testTime; i++){
    
    
            int[] arr1 = MergeSort.generateRandArray(maxSize, maxValue);
            int[] arr2 = MergeSort.copyArray(arr1);
            int count1 = countSUMOfSubArrInRange(arr1, 10, 50);  //O(NlogN)
            int count2 = comparator(arr2, 10, 50);  //O(N^2)
            if(count1 != count2){
    
    
                System.out.println("test failed!");
                System.out.println("accurate");
                System.out.println(count2);
                System.out.println("yours");
                System.out.println(count1);
            }
        }
        System.out.println("test pass!");
    }
}

提交版源码

class Solution {
    
    
    public int countRangeSum(int[] nums, int lower, int upper) {
    
    
      if(nums == null || lower > upper) return 0;
        //calculate preSum[]
        long[] preSum = new long[nums.length];
        preSum[0] = nums[0];
        for(int i = 1; i < nums.length; i++){
    
    
            preSum[i] = preSum[i - 1] + nums[i];
        }
        //! recursive entry
        return countPreSumInRange(preSum, 0, preSum.length - 1, lower, upper);
    }

    public int countPreSumInRange(long[] preSum, int L, int R, int lower, int upper){
    
    
        //!check sum of arr[0:R] (preSum[R]) isInRange, true then 1, false then 0
        if(L == R) return preSum[L] <= upper && preSum[L] >= lower ? 1 : 0;

        //check sum of arr[preSumL+1:R] isInRange
        //recursive
        int mid = L + ((R-L)>>1);
        return countPreSumInRange(preSum, L, mid, lower, upper)
                + countPreSumInRange(preSum, mid+1, R, lower, upper)
                + merge(preSum, L, R, lower, upper);
    }

    public int merge(long[] preSum, int L, int R, int lower, int upper){
    
            
        int count = 0;
        int preSumL = L;
        int preSumR = L;
        int mid = L + ((R-L)>>1);
        //calculate count of subArr in range
        for(int i = mid + 1; i <= R; i++){
    
      //! i from (mid + 1) to R
            //!each preSum[i] has a new range for preSum[preSumRange]
            long min = preSum[i] - upper;
            long max = preSum[i] - lower;
            //! <= max, then move preSumR
            while(preSumR <= mid && preSum[preSumR] <= max) preSumR++;
            //! <min, then move preSumL
            while(preSumL <= mid && preSum[preSumL] < min) preSumL++;
            count += preSumR - preSumL;
        }

        //merge preSum[]!
        long[] help = new long[R-L+1];
        int id = 0;
        int h1 = L;
        int h2 = mid + 1;
        while(h1 <= mid && h2 <= R) 
          help[id++] = preSum[h1] < preSum[h2] ? preSum[h1++] : preSum[h2++];
        while(h1 <= mid) help[id++] = preSum[h1++];
        while(h2 <= R) help[id++] = preSum[h2++];
        for(int i = 0; i < help.length; i++) preSum[L+i] = help[i];
        
        return count;
    }
}

视频讲解

对应 左程云算法体系班——class05 归并排序
老师的源码见:https://github.com/algorithmzuo/algorithmbasic2020/blob/master/src/class05/Code01_CountOfRangeSum.java

猜你喜欢

转载自blog.csdn.net/weixin_45549370/article/details/126085126