【LeetCode】327. Count of Range Sum(Hard)解题报告
题目地址:https://leetcode.com/problems/count-of-range-sum/description/
题目描述:
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.
Solution1:
/*
非常非常难得一道题
最优解是分治法,还可以用treemap,treeset,segement TREE
不懂
前n项和
time : O(n^2)
space : O(n)
*/
class Solution {
public int countRangeSum(int[] nums, int lower, int upper) {
if(nums == null || nums.length == 0) return 0;
TreeMap<Long,Long> treeMap = new TreeMap<>();
treeMap.put((long)0,(long)1);
long sum = 0;
long count = 0;
for(int i=0 ; i<nums.length ; i++){
sum += nums[i];
long from = sum - upper;
long to = sum - lower;
Map<Long,Long> sub = treeMap.subMap(from,true,to,true);
for(Long value : sub.values()){
count += value;
}
treeMap.put(sum , treeMap.getOrDefault(sum,(long)0)+1);
}
return (int)count;
}
}
Solution2:
/*
非常非常难得一道题
最优解是分治法,还可以用treemap,treeset,segement TREE
不懂,要多看
前n项和
time : O(nlogn)
space : O(n)
*/
class Solution {
public int countRangeSum(int[] nums, int lower, int upper) {
if(nums == null || nums.length == 0) return 0;
long[] sum = new long[nums.length + 1];
for(int i=1 ; i<=nums.length ; i++){
sum[i] = sum[i-1] + nums[i-1];
}
return helper(sum,new long[sum.length],0,sum.length-1,lower,upper);
}
private int helper(long[] sum,long[] helper,int low,int high,long lower,long upper){
if(low >= high) return 0;
int mid = (high + 1 - low) / 2 + low;
int count = helper(sum,helper,low,mid-1,lower,upper)
+helper(sum,helper,mid,high,lower,upper);
int rangeStart = mid, rangeEnd = mid;
for(int i=low ; i<mid ; i++){
while(rangeStart <= high && sum[rangeStart] - sum[i] < lower)
rangeStart++;
while(rangeEnd <= high && sum[rangeEnd] - sum[i] <= upper)
rangeEnd++;
count += rangeEnd - rangeStart;
}
merge(sum,helper,low,mid,high);
return count;
}
private void merge(long[] sum, long[] helper, int low,int mid, int high){
int left = low, right = mid, idx = low;
while(left < mid && right <= high){
if(sum[left] <= sum[right]){
helper[idx++] = sum[left++];
}else{
helper[idx++] = sum[right++];
}
}
while(left < mid){
helper[idx++] = sum[left++];
}
while(right <= high){
helper[idx++] = sum[right++];
}
System.arraycopy(helper,low,sum,low,high+1-low);
}
}
Date:2018年3月8日