327. Count of Range Sum 满足某个范围数内的区间个数

来源:互联网 发布:维稳大数据 编辑:程序博客网 时间:2024/06/04 01:28

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 = -2upper = 2,
Return 3.

The three ranges are : [0, 0][2, 2][0, 2] and their respective sums are: -2, -1, 2.


1.暴力求解

分别列出每个子区间,并计算个数

public int countRangeSum(int[] nums, int lower, int upper) {    int n = nums.length;    long[] sums = new long[n + 1];    for (int i = 0; i < n; ++i)        sums[i + 1] = sums[i] + nums[i];    int ans = 0;    for (int i = 0; i < n; ++i)        for (int j = i + 1; j <= n; ++j)            if (sums[j] - sums[i] >= lower && sums[j] - sums[i] <= upper)                ans++;    return ans;}


2. 合并排序

先计算【0,每个数】的区间和

切分成两部分【begin,mid】和【mid+1, end】,然后对i在【begin, mid】范围遍历,j在【mid+1, end】遍历中找到 count_lower = num[j]-num[i] < lower 和  count_upper = num[j]-num[i]  <= upper的个数,那么count_upper-count_lower就是满足给定范围的区间的个数 

(这里的解题思路很像找逆序对个数的解法)

最后返回总个数

编程时的注意点:

1.在merge的时候,开辟新数组赋值时,在循环中由于只赋值r前面的排好序的数,因此赋值回sum时只需把前r个赋值回去就行


class Solution {public:    int merge(vector<long>& sum, int begin, int mid, int end, int lower, int upper){        int n = end - begin + 1;        vector<long>array(n,0);        int low = mid+1, upp = mid+1, k = mid+1, r = 0;        int count = 0;        for(int i = begin; i <= mid; i++,r++){            while(low <= end && sum[low] - sum[i] < lower) low++;            while(upp <= end && sum[upp] - sum[i] <= upper) upp++;            while(k <= end && sum[k] < sum[i]) array[r++] = sum[k++];            array[r] = sum[i];            count += upp - low;        }        //这里只需赋值回前r个数        for(int i = 0; i < r; i++)            sum[i+begin] = array[i];        return count;    }                int sortmerge(vector<long>& sum, int begin, int end, int lower, int upper){        if(begin >= end)            return 0;        int mid = begin + (end - begin)/2;        int left = sortmerge(sum, begin, mid, lower, upper);        int right = sortmerge(sum, mid+1, end, lower, upper);        int res =  merge(sum, begin, mid, end, lower, upper);        return left + right + res;    }        int countRangeSum(vector<int>& nums, int lower, int upper) {        int n = nums.size();        vector<long>sum(n+1);        for(int i = 1; i <= n; i++)            sum[i] += sum[i-1] + nums[i-1];        return sortmerge(sum, 0, n, lower, upper);    }};

3.二叉查找树  (下次再补上)

0 0
原创粉丝点击