307 Range Sum Query - Mutable

这题可以用Segment tree写,不过用Segment Tree写起来太长了。
笔者从朋友那里听说了Binary Index Tree, 于是学习了Binary index tree的写法。
这个数据结构真是太牛了, 短短几行代码。
又学到了自己不知道 自己不知道 的东西。

BIT的大意就是把每个数的数值存在他自己,他爸爸,他的爷爷,他的爸爸的爷爷 上。。
那个谁是他的爸爸呢?他自己加上他的最低非零位就是他的爸爸。
比如1的爸爸是2, 2的爸爸是2 + 2 = 4
3的爸爸不是 6, 而是 3 + 1 = 4
4的爸爸是8,
5的爸爸是6 = 5 + 1
6的爸爸是8
1 上面只存他自己
2上面存 1,2的和
3上面只存他自己
4上面存1,2,3,4的和
5上面只存他自己
6上面存 5,6的和
7上面只存他自己,
8上面存 1-8的 和
看二进制码就容易一些
11的二进制码是 1011, 他的父亲就是1011 + 1 = 1100 =(12)
12的 二进制码是1100,他的父亲就是10000(16)
运算起来就是 i + (i & (-i)) 就是i的父亲, (i & (-i))是取最低非 0位。
参考资料
https://leetcode.com/problems/range-sum-query-mutable/discuss/75753/Java-using-Binary-Indexed-Tree-with-clear-explanation

class NumArray {
    int[] bitTree;
    int[] nums;
    int n;
    public NumArray(int[] nums) {
        this.nums = nums;
        n = nums.length;
        bitTree = new int[n + 1];
        for (int i = 0; i < n; i++) updateTree(bitTree, i + 1, nums[i]);
    }
    
    public void update(int i, int val) {
        updateTree(bitTree, i + 1, val - nums[i]);
        nums[i] = val;
    }
    
    public int sumRange(int i, int j) {
        return getSum(j + 1) - getSum(i - 1 + 1);
    }
    private void updateTree(int[] bTree, int index, int diff) {
        while (index <= n) {
            bTree[index] += diff;
            index += (index & -index);
        }
    }
    private int getSum(int index) {
        int ans = 0;
        while (index > 0) {
            ans += bitTree[index];
            index -= (index &(-index));
        }
        return ans;
    }
}

你可能感兴趣的:(307 Range Sum Query - Mutable)