leetcode 327. 区间和的个数
问题描述: 给你一个整数数组 nums 以及两个整数 lower 和 upper 。求数组中,值位于范围 [lower, upper] (包含 lower 和 upper)之内的 区间和的个数 。
区间和 S(i, j) 表示在 nums 中,位置从 i 到 j 的元素之和,包含 i 和 j (i ≤ j)。
示例 1:
输入: nums = [-2,5,-1], lower = -2, upper = 2
输出: 3
解释: 存在三个区间:[0,0]、[2,2] 和 [0,2] ,对应的区间和分别是:-2 、-1 、2 。
示例 2:
输入: nums = [0], lower = 0, upper = 0
输出: 1
思路: 归并排序的思想
/**
* @param {number[]} nums
* @param {number} lower
* @param {number} upper
* @return {number}
*/
// 获取前缀和
var countRangeSum = function(nums, lower, upper) {
let arr=new Array(nums.length+1).fill(0);
arr[0]=0;
for(let i=0;i<nums.length;i++)arr[i+1]=arr[i]+nums[i];
return getCount(arr, 0,arr.length-1,lower, upper);
};
//排序过程中求职,对左侧值求右侧范围(因为排序之后的)
function getCount(nums, l,r,lower, upper){
if(l>=r)return 0;
let count=0;
let mid=Math.floor((l+r)/2);
count+=getCount(nums, l,mid,lower, upper)
count+=getCount(nums, mid+1,r,lower, upper)
count+=rangeTwoSide(nums, l,mid,mid+1,r,lower, upper)
let l1=l;let r1=mid+1;let k=0;let temp=[];
while(l1<=mid||r1<=r){
if(r1>r||l1<=mid&&nums[l1]<=nums[r1]){
temp[k++]=nums[l1++];
}else{
temp[k++]=nums[r1++]
}
}
for(let i=0;i<temp.length;i++)nums[i+l]=temp[i];
return count;
}
function rangeTwoSide(nums, l1,l2,r1,r2,lower, upper){
let k1=l1;let k2=l1;
let ans=0;
for(let i=r1;i<=r2;i++){
let b=nums[i]-lower;
let a=nums[i]-upper;
while(k1<=l2&&nums[k1]<a)k1++
while(k2<=l2&&nums[k2]<=b)k2++;
ans+=k2-k1
}
return ans
}