LeetCode_327 Count of Range Sum
来源:互联网 发布:淘宝赤兔插件备注设置 编辑:程序博客网 时间:2024/06/08 17:35
LeetCode_327 Count of Range Sum
题目描述
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(
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
.
Credits:
Special thanks to @dietpepsi for adding this problem and creating all test cases.
Link:
https://leetcode.com/problems/count-of-range-sum/description/
解决方案
本题是求数组的区间和在给定范围内的个数。数组的区间和s(i,j)
指的是索引在i
与j
(i
j
)之间的所有元素的和,给定范围在[lower,upper]
之间,求出所有满足lower
s(i,j)
upper
的区间[i,j]
的个数。
由之前类似的题目Range Sum Query - Immutable,Range Sum Query 2D - Immutable 和 Range Sum Query - Mutable,求区间和的问题一般是先计算累加和sums[i]
=nums[0]
+nums[1]
+ ··· +nums[i]
,则s(i,j)
=sums[j]
-sums[i]
。
通过参考资料,解决该题的基本思想是:
- 对累加和数组的某个元素
sums[i]
,对其之后(或之前)的元素进行排序。 - 对于有序序列sorted[start,end],找出满足
sorted[j]
≥ lower
的第一个sorted[j]和满足sorted[k]
> upper
的第一个sorted[k]
,则k-j
即为数组中在[lower,upper]
范围内的所有元素的个数。
下面是两种解法,其中解法一被使用和引用的最多。
解法一
采用“归并排序(Merge Sort)”来求解,基本思路是将累加和数组sums[start,end]
分为左右两半,其中左半部[start,mid)
和右半部[mid,end)
先分别递归调用解法一求出各自的满足条件的区间和个数,并完成各自部分的排序。然后再将已经排好序的左右两部进行归并,完成整体排序。在整体排序过程中,遍历左半部分的sums[i]
,找出右半部分的sums[j]
和sums[k]
,使其满足:
sums[j]
是第一个满足sums[j]
− sums[i]
≥ lower
的元素。sums[k]
是第一个满足sums[k]
− sums[i]
> upper
的元素。
则k-j
便是在[lower,upper]
之间的区间和的个数。因为采用自底向上的归并排序,所以保证了对每一个sums[i]
,能够找到其后所有满足条件的sums[j]
和sums[k]
。
在整体排序的过程中,还需要一个缓存数组cache
来存储每次遍历i
时的左右半排序结果,通过复制完成sums[start,end]
间的整体排序。
以下为源码:
//C++ Merge Sortclass Solution {public: int countRangeSum(vector<int>& nums, int lower, int upper) { int len=nums.size(); vector<long long> sums(len+1,0); for(int i=0;i<len;i++){ sums[i+1]=sums[i]+nums[i]; } return countAndMergeSort(sums,0,len+1,lower,upper); } int countAndMergeSort(vector<long long>& sums,int start,int end,int lower,int upper){ if(end-start<=1)return 0; vector<long long> cache(end-start); int middle=(start+end)/2; int cnt=countAndMergeSort(sums,start,middle,lower,upper)+ countAndMergeSort(sums,middle,end,lower,upper); int j=middle,k=middle,t=middle; int r=0; for(int i=start;i<middle;++i){ while(j<end && sums[j]-sums[i]<lower)j++; while(k<end && sums[k]-sums[i]<=upper)k++; while(t<end && sums[t]<sums[i])cache[r++]=sums[t++]; cache[r++]=sums[i]; cnt+=k-j; } copy(cache.begin(),cache.begin()+r,sums.begin()+start); return cnt; }};
解法二
使用multiset,遍历nums[i]
,逐一将i
位置的累加和插入到multiset中,保证已经插入的累加和有序。对于位置i
,multiset中已经有按序排列的前i
个累加和。目标是找到i
前的满足条件lower
sums[i]
sums[j]
upper
的sums[j]
的个数,即寻找满足条件 sums[i]
upper
sums[j]
sums[i]
lower
的两个临界值之间的元素个数。临界值可以使用lower_bound
(返回有序集合中大于等于给定值的第一个数)和upper_bound
(返回有序集合中大于给定值的第一个数)来求得。
以下为源码:
//C++ multisetclass Solution {public: int countRangeSum(vector<int>& nums, int lower, int upper) { multiset<long long> sums; sums.insert(0); int res=0; long long sum=0; for(int i=0;i<nums.size();i++){ sum+=nums[i]; res+=distance(sums.lower_bound(sum-upper),sums.upper_bound(sum-lower)); sums.insert(sum); } return res; }};
相关题目
LeetCode_303 Range Sum Query - Immutable
LeetCode_304 Range Sum Query 2D - Immutable
LeetCode_307 Range Sum Query - Mutable
参考资料
https://leetcode.com/problems/count-of-range-sum/discuss/
https://www.cnblogs.com/grandyang/p/5162678.html
- LeetCode_327 Count of Range Sum
- 2017-09-14 LeetCode_327 Count of Range Sum
- Count of Range Sum
- leetcode Count of Range Sum
- 327Count of Range Sum
- LeetCode Count of Range Sum
- [LeetCode]Count of Range Sum
- 327. Count of Range Sum
- Leetcode Count of Range Sum
- 327. Count of Range Sum
- leetcode Count of Range Sum
- 327. Count of Range Sum
- []LeetCode]Count of Range Sum
- 327. Count of Range Sum
- [LeetCode] Count of Range Sum
- 327. Count of Range Sum
- 327. Count of Range Sum
- Count of Range Sum(leetcode)
- 动画
- 看看滴滴大牛是如何从码农到AI的华丽转身
- Andrew Ng deeplearning.ai专项课程第四课Convolutional Neural Networks第一周笔记
- [Search Engines笔记] 16: Ranked retrieval: Feature-based models
- 12年经验老程序员的5次转型
- LeetCode_327 Count of Range Sum
- PTA计算职工工资
- 画叉号的简单方法
- 杜利特尔分解法Doolittle(LU分解法)_解线性方程组的直接解法
- 初学iOS,刚看到控件的strong&weak问题,如果答的不对还请指正。首先有一点,在OC中,如果对象没有强引用,就会被自动释放,那么为什么控件还可以设为weak?
- 快讯丨北京出台中国首个自动驾驶法规,北京第一批测试道路将推出
- 用百度获取网络数据
- 经济学人万字总结17年AI领域并购趋势:谷歌领跑,人才竞争白热化
- 重磅译制 | 更新:牛津大学xDeepMind自然语言处理 第6讲(上)NLP硬件和软件-英伟达GPU