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.
参考 https://discuss.leetcode.com/topic/33738/share-my-solution
思路是用mergesort的原理,利用归并的左右两部分都是有序的,那么对于左边的每一个sums[i],都有count+=j-k,其中j为右半部分第一个大于upper的索引,k为右半部分第一个大于等于lower的索引,sums[i]代表数组i的前缀和,代码:
public int countRangeSum(int[] nums, int lower, int upper) { long[] sums=new long[nums.length+1]; for(int i=0;i<sums.length-1;i++){ sums[i+1]=sums[i]+nums[i]; } return mergeSort(sums,0, sums.length-1,lower,upper); } public int mergeSort(long[] nums,int begin,int end,int lower,int upper){ if(begin>=end) return 0; int mid=(begin+end)/2; int count=mergeSort(nums,begin,mid,lower,upper)+mergeSort(nums,mid+1,end,lower,upper); int i=begin,j=mid+1,k=mid+1,t=mid+1; long temp[]=new long[end-begin+1]; int tindex=0; for(;i<=mid;i++,tindex++){ while(j<=end&&nums[j]-nums[i]<lower) j++; while(k<=end&&nums[k]-nums[i]<=upper) k++; while(t<=end&&nums[t]<nums[i]) temp[tindex++]=nums[t++]; temp[tindex]=nums[i]; count+=k-j; } System.arraycopy(temp,0,nums,begin,t-begin); return count; }