Given an integer array nums
, return the number of range sums that lie in [lower, upper]
inclusive.
Range sum S(i, j)
is defined as the sum of the elements in nums
between indices i
and
j
(i
≤ j
), inclusive.
Note:
A naive algorithm of O(n2) is trivial. You MUST do better than that.
Example:
Given nums = [-2, 5, -1]
, lower = -2
, upper = 2
,
Return 3
.
The three ranges are : [0, 0]
, [2, 2]
, [0, 2]
and their respective sums are: -2, -1, 2
.
Credits:
Special thanks to @dietpepsi for adding this problem and creating all test cases.
Analysis:
See this post: http://huntzhan.org/leetcode-count-of-range-sum/
Solution:
Divide and Conquer O(nlogn)
1 public class Solution { 2 public int countRangeSum(int[] nums, int lower, int upper) { 3 if (nums.length==0) return 0; 4 5 long[] sums = new long[nums.length]; 6 long sum = 0; 7 for (int i=0;i<nums.length;i++){ 8 sum += nums[i]; 9 sums[i] = sum; 10 } 11 12 int res = countRangeSumRecur(sums,0,sums.length-1,lower,upper); 13 14 return res; 15 } 16 17 public int countRangeSumRecur(long[] sums, int start, int end, int lower, int upper){ 18 if (start==end){ 19 return (sums[start]>=lower && sums[start]<=upper) ? 1 : 0; 20 } 21 22 int len = end-start+1; 23 long[] cache = new long[len]; 24 int mid = (start+end)/2; 25 int leftCount = countRangeSumRecur(sums,start,mid,lower,upper); 26 int rightCount = countRangeSumRecur(sums,mid+1,end,lower,upper); 27 int res = leftCount + rightCount; 28 29 // Count those cross left part and right part. 30 int l1 = start, r1 = mid+1, r2 = mid+1, i1=mid+1; 31 int ind = 0; 32 while (l1<mid+1){ 33 // Get r1 and r2 into correct places. 34 while (r1<=end && sums[r1]-sums[l1]<lower) r1++; 35 while (r2<=end && sums[r2]-sums[l1]<=upper) r2++; 36 res += r2-r1; 37 38 // Perform sorting work. 39 while (i1<=end && sums[i1]<=sums[l1]){ 40 cache[ind++] = sums[i1++]; 41 } 42 cache[ind++] = sums[l1]; 43 l1++; 44 } 45 while (i1<=end){ 46 cache[ind++] = sums[i1++]; 47 } 48 49 for (int i=0;i<len;i++){ 50 sums[start+i] = cache[i]; 51 } 52 53 return res; 54 } 55 }