LeetCode 327. Count of Range Sum

对于count 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.

public int countRangeSum(int[] nums, int lower, int upper)
要注意 这里给的lower和upper不是index而是指的一个数值范围。 这道题目实际上问的是 在所有的subarray中sum在给定的[lower, upper]范围里的有多少。

当然 这道题目很容易用O(n^2)的方式去解。
但是题目要求不能用。
所以我们必须要像一个办法快速得到所有的sum然后check是否在规定范围中。

this problem is way too hard for me too.
and according to the solution, it can be solved in two ways:
divide and conquer, and Binary index tree(树状数组)

这是一道典型的树状数组问题 因此就只看树状数组的解法:
reference: https://leetcode.com/problems/count-of-range-sum/discuss/78006/Summary-of-the-Divide-and-Conquer-based-and-Binary-Indexed-Tree-based-solutions

public int countRangeSum(int[] nums, int lower, int upper) {
    long[] sum = new long[nums.length + 1];
    long[] cand = new long[3 * sum.length + 1];
    int index = 0;
    cand[index++] = sum[0];
    cand[index++] = lower + sum[0] - 1;
    cand[index++] = upper + sum[0];

    for (int i = 1; i < sum.length; i++) {
        sum[i] = sum[i - 1] + nums[i - 1];
        cand[index++] = sum[i];
        cand[index++] = lower + sum[i] - 1;
        cand[index++] = upper + sum[i];
    }

    cand[index] = Long.MIN_VALUE; // avoid getting root of the binary indexed tree when doing binary search
    Arrays.sort(cand);

    int[] bit = new int[cand.length];

    // build up the binary indexed tree with only elements from the prefix array "sum"
    for (int i = 0; i < sum.length; i++) {
        addValue(bit, Arrays.binarySearch(cand, sum[i]), 1);
    }

    int count = 0;

    for (int i = 0; i < sum.length; i++) {
        // get rid of visited elements by adding -1 to the corresponding tree nodes
        addValue(bit, Arrays.binarySearch(cand, sum[i]), -1);

        // add the total number of valid elements with upper bound (upper + sum[i])
        count += query(bit, Arrays.binarySearch(cand, upper + sum[i]));

        // minus the total number of valid elements with lower bound (lower + sum[i] - 1)
        count -= query(bit, Arrays.binarySearch(cand, lower + sum[i] - 1));
    }

    return count;
}

private void addValue(int[] bit, int index, int value) {
    while (index < bit.length) {
        bit[index] += value;
        index += index & -index;
    }
}

private int query(int[] bit, int index) {
    int sum = 0;
    
    while (index > 0) {
        sum += bit[index];
        index -= index & -index;
    }
    return sum;
}
posted @ 2020-11-11 00:15  EvanMeetTheWorld  阅读(43)  评论(0)    收藏  举报