思路:首先想到的还是暴力搜索,这时时间复杂度为O(N2),N2的复杂度再降就是NlogN了,而是就是二分的思想,把大数据转化为求一堆小数据。想法很像归并排序,当然不是排序了。见代码二,AC。
时间复杂度分析:对问题研究为T(N) = 2*T(N/2) + (N/2)^2,这个公式计算之后仍然了O(N2)的复杂度。不过已经比暴力搜索快得多了。
代码一(TLE)
public class Solution {
public int countRangeSum(int[] nums, int lower, int upper) {
int length = nums.length;
if(length <= 0)
return 0;
long counts[] = new long[nums.length];
counts[0] = nums[0];
for(int i = 1;i<nums.length;i++){
counts[i] = counts[i-1]+nums[i];
}
int count = 0;
for(int i = 0;i<length;i++){
for(int j = i;j<length;j++){
long num = counts[j] - counts[i] + nums[i];
if(num >= lower && num <= upper)
count++;
}
}
return count;
}
}
代码二(AC)
public class Solution {
long[] counts;
int lower,upper;
public int countRangeSum(int[] nums, int lower, int upper) {
int length = nums.length;
this.lower = lower;this.upper = upper;
if(length <= 0)
return 0;
counts = new long[nums.length];
counts[0] = nums[0];
for(int i = 1;i<nums.length;i++){
counts[i] = counts[i-1]+nums[i];
}
return countNum(nums,0,length-1);
}
private int countNum(int[] nums,int left,int right){
if(left == right){
if(nums[left] >=lower && nums[right] <= upper)
return 1;
return 0;
}
int mid = (left+right)/2;
int total = 0;
for(int i = left;i<=mid;i++){
for(int j = mid+1;j<=right;j++){
long tmpNum = counts[j] - counts[i] + nums[i];
if(tmpNum >= lower && tmpNum <= upper)
++total;
}
}
//采用二分法
return total + countNum(nums,left,mid) + countNum(nums,mid+1,right);
}
}