leetcode 327. Count of Range Sum

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(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.


分治法来处理. 

0、sum[i]表示前i项的和。这一点是关键,用来计算的是sum[i]

1、 利用归并排序算法的将数组分成左右两边,

2、分别算左右两截的内部的可能的情况。

3、在这两截合并组成 满足的 情况的算法:

循环在第一截中遍历起始点。

在第二截中找结束点,看有多少种满足的情况。找结束点的方式是:

  在合并左右数组的时候对于左边数组中的每一个元素在右边数组找到一个范围, 使得在这个范围中的的元素与左边的元素构成的区间和落在[lower, upper]之间.  即在右边数组找到两个边界, 设为m, n, 其中m是在右边数组中第一个使得sum[m]- sum[i] >= lower的位置, n是第一个使得sum[n] - sum[i] > upper的位置, 这样n-m就是与左边元素i所构成的位于[lower,upper]范围的区间个数. 

4、再把左右两截范围的sum排序。sum排序是这个算法做下去的关键。


其时间复杂度为O(n log n)


注:

inplace_merge函数的作用和merge函数差不多,只不过是在一个容器中进行归并。函数参数:inplace_merge(first,mid,last,compare);//将[first,mid) 和 [mid,last)这两个区间进行归并成一个有序序列。[first,mid)和[mid,last)都要呈升序或降序排列!



class Solution {
public:
    int mergeSort(vector<long>& sum, int lower, int upper, int low, int high)  
    {  
        if (high <= low + 1) 
            return 0;  
        int mid = (low + high) / 2, m = mid, n = mid, count = 0;  
        count = mergeSort(sum,lower,upper,low,mid) + mergeSort(sum,lower,upper,mid,high);//左右两截内部的可能的结果
        for (int i = low; i < mid; i++) //遍历 第一截 中的起始点
        {  
            while (m < high && sum[m] - sum[i] < lower) m ++;   //因为是 两截中的 sum 是排好序的 所以可以用差值来计算 结束点的距离 
            while (n < high && sum[n] - sum[i] <= upper) n ++;  
            count += n - m;  
        }  
        //把两截的sum归并排序。因为这一截内部的已经算完。顺序没有关系了。
        inplace_merge(sum.begin() + low, sum.begin() + mid, sum.begin() + high); 
        return count;  
    }  
  
    int countRangeSum(vector<int>& nums, int lower, int upper) 
    {  
        int len = nums.size();  
        vector<long> sum(len + 1, 0);  
        for (int i = 0; i < len; i++) 
            sum[i+1] = sum[i] + nums[i];  
        return mergeSort(sum, lower, upper, 0, len+1);  
    }  
};


参考:http://blog.csdn.net/qq508618087/article/details/51435944


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值