LeetCode 327. Count of Range Sum

无意看到的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的。

 1 class Solution {
 2 public:
 3     int lo,hi;
 4     int ret=0;
 5     void msort(vector<long long>& A,int x,int y,vector<long long>& T) {
 6         if (y-x<=1) {
 7             if (A[x]>=lo&&A[x]<=hi) ret++;
 8             return;
 9         }
10         int mid=x+(y-x)/2;
11 
12         msort(A,x,mid,T);
13         msort(A,mid,y,T);
14         int p=x,q=mid,it=x;
15         int j1=x,j2=x;
16         for (int i=mid;i<y;i++) {
17             while (j1<mid&&A[i]-A[j1]>=lo)
18                 j1++;
19             while (j2<mid&&A[i]-A[j2]>hi)
20                 j2++;
21             ret+=j1-j2;
22         }
23         while (p<mid||q<y) {
24             if (q>=y||(p<mid&&A[p]<=A[q]))
25                 T[it++]=A[p++];
26             else
27                 T[it++]=A[q++];
28         }
29         for (int i=x; i<y; i++)
30             A[i]=T[i];
31     }
32     int countRangeSum(vector<int>& nums, int lower, int upper) {
33         if (nums.size()==0) return 0;
34         ret=0;
35         lo=lower,hi=upper;
36         vector<long long> temp(nums.size(),0);
37         vector<long long> vec;
38         vec.push_back(nums[0]);
39         for (int i=1;i<nums.size();i++)
40             vec.push_back(nums[i]+vec[i-1]);
41         msort(vec,0,vec.size(),temp);
42         return ret;
43     }
44 };
View Code

 

posted @ 2016-02-02 00:45  活在夢裡  阅读(1811)  评论(0编辑  收藏  举报