题目:
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
.
翻译:
给定一个整数数组nums,返回位于[lower,upper](含)的范围和的个数。
范围和S(i,j)被定义为索引i和j(i≤j)之间的num中的元素的总和,包括j和j。
注意:
O(n2)的朴素算法是微不足道的。 你必须做得更好。
例:
给定nums = [-2,5,-1],下限= -2,上限= 2,
返回3。
三个范围是:[0,0],[2,2],[0,2]以及它们各自的和为:-2,-1,2。
解题思路:
递归思路,将 arr[] 均分为两半, 后一半使用sums[] 对应表示 从中间到对应下标的和,然后将sums排序,从 middle向低循环二叉检索
在sums中符合在lower和upper中的个数。
代码展示:
#include<iostream>
#include<algorithm>
#include<vector>
#include <stdio.h> /* printf */
#include <stdlib.h>
using namespace std;
//快排比较函数
int comp (const void * a, const void * b)
{
if(*(long*)a > *(long*)b ) return 1;
else if(*(long*)a < *(long*)b ) return-1;
else return 0;
}
class Solution {
//从arr[]中二叉搜索找到比 target大的元素个数
int findBigger(long* arr,double target,int begin,int end) {
if(arr[end] < target) return 0;
if(arr[begin] > target) return end - begin+1;
int l = begin ,r = end;
while(l<r) {
int middle = (l+r)/2;
if(arr[middle] < target && arr[middle+1] > target) return end-middle;
else if(arr[middle] > target) r = middle;
else l = middle;
}
return 0;
}
//递归算法
int countSub(vector<int>& nums,int begin,int end,int lower,int upper) {
//递归基
if(begin == end) return (nums[begin] >= lower&&nums[begin] <= upper)?1:0;
if(begin > end) return 0;
int middle = (begin+end)/2;
long sumsSecond[end-middle] = {0};// sumsSecond[i] 表示 nums 从middle 到middle+i 的和
long sumTemp = 0;
for(int i = middle+1 ;i <= end ;i++) {
sumTemp+= nums[i];
sumsSecond[i-middle-1] = sumTemp;
}
//将后一半的迭代和排序
qsort(sumsSecond,end-middle,sizeof(long),comp);
int count = 0;
sumTemp = 0;
for(int i = middle;i>=begin;i--) {
sumTemp+= nums[i];
count += findBigger(sumsSecond,lower-sumTemp-0.5,0,end-middle-1) -findBigger(sumsSecond,upper-sumTemp+0.5,0,end-middle-1);
}
return countSub(nums,begin,middle,lower,upper)+ countSub(nums,middle+1,end,lower,upper) + count;
}
public:
int countRangeSum(vector<int>& nums, int lower, int upper) {
int len = nums.size();
if(len==0) return 0;
if(len == 1) return (nums[0] >= lower&&nums[0] <= upper)?1:0;
return countSub(nums,0,len-1,lower,upper);
}
};
int main() {
Solution p;
int a[] = {-2, 5, -1};
vector<int> v(a,a+3);
// cout << v.size()<<endl;
int lower = -2, upper = 2;
cout <<p.countRangeSum(v,lower,upper)<<endl;
}
题目状态: