[路飞]_js算法:leetcode 327-区间和的个数

100 阅读1分钟

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 、-12

示例 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
}