LeetCode 327. Count of Range Sum
2016-02-02 00:45
435 查看
无意看到的LeetCode新题,不算太简单,大意是给一个数组,询问多少区间和在某个[L,R]之内。首先做出前缀和,将问题转为数组中多少A[j]-A[i] (j>i)在范围内。
有一种基于归并排序的做法,在每次归并完左右两个子区间后,当前区间两部分分别都已经排序完毕,基于有序这一点,扫描后半段区间,对于每个A[i] (i>=mid),目标区间即为[ A[i]-R, A[i]-L ], 对于有序数组来说,求出元素落在某一区间的个数直接就是upper_bound-lower_bound,事实上,这里我们只需要另外两个浮动于前半段区间的指针即可动态维护upper_bound和lower_bound,因为查询目标区间的两个端点是不断递增的。
归并排序是以前抄自刘汝佳白书的左闭右开版,递归边界条件(只有一个数)做一下特判。另外LeetCode题目本身也需要注意许多边边角角的trick,比如输入vector为空,元素加加减减溢出的情况,所以直接无脑long long就好。
题外话,不知为何输出是一个int,按理如果卡O(n^2)的话,数据规模必然做到可以构造答案溢出int_max的。
View Code
有一种基于归并排序的做法,在每次归并完左右两个子区间后,当前区间两部分分别都已经排序完毕,基于有序这一点,扫描后半段区间,对于每个A[i] (i>=mid),目标区间即为[ A[i]-R, A[i]-L ], 对于有序数组来说,求出元素落在某一区间的个数直接就是upper_bound-lower_bound,事实上,这里我们只需要另外两个浮动于前半段区间的指针即可动态维护upper_bound和lower_bound,因为查询目标区间的两个端点是不断递增的。
归并排序是以前抄自刘汝佳白书的左闭右开版,递归边界条件(只有一个数)做一下特判。另外LeetCode题目本身也需要注意许多边边角角的trick,比如输入vector为空,元素加加减减溢出的情况,所以直接无脑long long就好。
题外话,不知为何输出是一个int,按理如果卡O(n^2)的话,数据规模必然做到可以构造答案溢出int_max的。
class Solution { public: int lo,hi; int ret=0; void msort(vector<long long>& A,int x,int y,vector<long long>& T) { if (y-x<=1) { if (A[x]>=lo&&A[x]<=hi) ret++; return; } int mid=x+(y-x)/2; msort(A,x,mid,T); msort(A,mid,y,T); int p=x,q=mid,it=x; int j1=x,j2=x; for (int i=mid;i<y;i++) { while (j1<mid&&A[i]-A[j1]>=lo) j1++; while (j2<mid&&A[i]-A[j2]>hi) j2++; ret+=j1-j2; } while (p<mid||q<y) { if (q>=y||(p<mid&&A[p]<=A[q])) T[it++]=A[p++]; else T[it++]=A[q++]; } for (int i=x; i<y; i++) A[i]=T[i]; } int countRangeSum(vector<int>& nums, int lower, int upper) { if (nums.size()==0) return 0; ret=0; lo=lower,hi=upper; vector<long long> temp(nums.size(),0); vector<long long> vec; vec.push_back(nums[0]); for (int i=1;i<nums.size();i++) vec.push_back(nums[i]+vec[i-1]); msort(vec,0,vec.size(),temp); return ret; } };
View Code