*Depr:一个整数数组 nums,返回区间和在 [lower, upper] 之间的个数,包含 lower 和 upper。
区间和 S(i, j) 表示在 nums 中,位置从 i 到 j 的元素之和,包含 i 和 j (i ≤ j)。
说明:
最直观的算法复杂度是 O(n2) ,请在此基础上优化你的算法。
示例:
输入: nums = [-2,5,-1], lower = -2, upper = 2,
输出: 3
解释: 3个区间分别是: [0,0], [2,2], [0,2],它们表示的和分别为: -2, -1, 2。
coding
`class Solution {
public int countRangeSum1(int[] nums, int lower, int upper) {
int res = 0;
//O(n^2)
for(int i=0;i<nums.length;i++) {
long sum = 0;
for(int j=i;j<nums.length;j++) {
sum = sum+nums[j];
if(sum>=lower && sum<=upper) {
res++;
}
}
}
return res;
}
// 优化解法(使用TreeMap)
public int countRangeSum2(int[] nums, int lower, int upper) {
if (nums == null || nums.length == 0) {
return 0;
}
TreeMap<Long, Integer> map = new TreeMap<>();
long[] sums = new long[nums.length];
sums[0] = nums[0];
for (int i = 1; i < nums.length; i++) {
sums[i] = sums[i - 1] + nums[i];
}
int res = 0;
for (int i = 0; i < nums.length; i++) {
if (sums[i] >= lower && sums[i] <= upper) {
res++;
}
for (Integer count : map.subMap(sums[i] - upper, true, sums[i] - lower, true).values()) {
res += count;
}
Integer count = map.get(sums[i]);
if (count == null) {
count = 1;
}else {
count++;
}
map.put(sums[i], count);
}
return res;
}
//Merge
//利用归并排序(O(nlogn))
public static int countRangeSum(int[] nums, int lower, int upper) {
if(nums==null || nums.length==0) {
return 0;
}
long[] sums = new long[nums.length];
sums[0] = nums[0];
for(int i=1;i<nums.length;i++) {
sums[i] = nums[i]+sums[i-1];
}
return Merge(sums, 0, sums.length-1, lower, upper);
}
private static int Merge(long[] sums,int s,int e,int lower,int upper) {
if (s >= e) {
if(sums[s]>=lower && sums[s]<=upper) {
return 1;
}else {
return 0;
}
}
int mid = (s+e)/2;
int r1 = mid+1;
int r2 = mid+1;
long[] copy = new long[e-s+1]; //临时数组
int res = Merge(sums, s, mid, lower, upper)+Merge(sums, mid+1, e, lower, upper); //归并排序
for(int i = s ; i <= mid ; i ++)
{
while(r1 <= e && sums[r1] - sums[i] < lower) {
r1++;
}
while(r2 <= e && sums[r2] - sums[i] <= upper) {
r2 ++;
}
res += (r2 - r1);
}
//进行排序合并
int k = copy.length-1;
int a = mid;
int b = e;
while(a>=s && b>mid){
if(sums[a]>=sums[b]){
copy[k--] = sums[a--];
}else{
copy[k--] = sums[b--];
}
}
while(a>=s){
copy[k--] = sums[a--];
}
while(b>mid){
copy[k--] = sums[b--];
}
System.arraycopy(copy,0,sums,s,e-s+1);
return res;
}
}`**