Leetcode 327. Número de sumas de intervalo

Leetcode 327. Número de sumas de intervalo

Análisis de ideas

inserte la descripción de la imagen aquí
inserte la descripción de la imagen aquí

Código fuente de la versión de autoprueba

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!");
    }
}

Enviar código fuente de versión

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;
    }
}

Vídeo explicativo

Correspondiente a la clase del sistema de algoritmos Zuo Chengyun:
código fuente del profesor de clasificación de combinación de clase 05: https://github.com/algorithmzuo/algorithmbasic2020/blob/master/src/class05/Code01_CountOfRangeSum.java

Supongo que te gusta

Origin blog.csdn.net/weixin_45549370/article/details/126085126
Recomendado
Clasificación