20.11.7 leetcode327 区间和的个数

题目链接:https://leetcode-cn.com/problems/count-of-range-sum/

题意:给一个整型的数组,求数组内有多少区间的区间和位于[lower,upper]中。

分析:用前缀和数组来处理,这样区间(i,j)和就可以简单理解为pres[j]-pres[i]。一个比较简单的想法是将前缀和数组排序,然后从第一个当被减数做起,后面的与它差值在[lower,upper】之间的就是符合要求的,但有问题的是因为数组中存在负数,排序后可能前面的前缀和排到后面去了,会出现前面的前缀和减后面的这种无效情况。所以我们可以采用归并的思想,左半段和右半段分别排序,在做半段里面找被减数,右半段是减数。

class Solution {
public:
    int countRangeSumRecursive(vector<long>& sum, int lower, int upper, int left, int right) {
        if (left == right) {
            return 0;
        } else {
            int mid = (left + right) / 2;
            int n1 = countRangeSumRecursive(sum, lower, upper, left, mid);
            int n2 = countRangeSumRecursive(sum, lower, upper, mid + 1, right);
            int ret = n1 + n2;

            // 首先统计下标对的数量
            int i = left;
            int l = mid + 1;
            int r = mid + 1;
            while (i <= mid) {
                while (l <= right && sum[l] - sum[i] < lower) l++;
                while (r <= right && sum[r] - sum[i] <= upper) r++;
                ret += (r - l);
                i++;
            }

            // 随后合并两个排序数组
            vector<int> sorted(right - left + 1);
            int p1 = left, p2 = mid + 1;
            int p = 0;
            while (p1 <= mid || p2 <= right) {
                if (p1 > mid) {
                    sorted[p++] = sum[p2++];
                } else if (p2 > right) {
                    sorted[p++] = sum[p1++];
                } else {
                    if (sum[p1] < sum[p2]) {
                        sorted[p++] = sum[p1++];
                    } else {
                        sorted[p++] = sum[p2++];
                    }
                }
            }
            for (int i = 0; i < sorted.size(); i++) {
                sum[left + i] = sorted[i];
            }
            return ret;
        }
    }

    int countRangeSum(vector<int>& nums, int lower, int upper) {
        long s = 0;
        vector<long> sum{0};
        for(auto& v: nums) {
            s += v;
            sum.push_back(s);
        }
        return countRangeSumRecursive(sum, lower, upper, 0, sum.size() - 1);
    }
};

 

posted @ 2020-11-07 20:14  清酒令  阅读(110)  评论(0编辑  收藏  举报