LeetCode[307]Range Sum Query

来源:互联网 发布:淘宝客服视频教程 编辑:程序博客网 时间:2024/06/05 03:00

Description:

Given an integer array nums, find the sum of the elements between indices i and j (i ≤ j), inclusive.

The update(i, val) function modifies nums by updating the element at index i to val.

Example:

Given nums = [1, 3, 5]sumRange(0, 2) -> 9update(1, 2)sumRange(0, 2) -> 8

Note:

  1. The array is only modifiable by the update function.
  2. You may assume the number of calls to update and sumRange function is distributed evenly.

树状数组:
已知数组A[ ],则建立树状数组C[ ],则C[ ]满足:
C1 = A1
C2 = A1 + A2
C3 = A3
C4 = A1 + A2 + A3 + A4
C5 = A5
C6 = A5 + A6
C7 = A7
C8 = A1 + A2 + A3 + A4 + A5 + A6 + A7 + A8
...
C16 = A1 + A2 + A3 + A4 + A5 + A6 + A7 + A8 + A9 + A10 + A11 + A12 + A13 + A14 + A15 + A16
当想要查询一个SUM(n)(求a[n]的和),可以依据如下算法即可:
step1: 令sum = 0,转第二步;
step2: 假如n <= 0,算法结束,返回sum值,否则sum = sum + C[n],转第三步;
step3: 令n = n – lowbit(n),转第二步。
可以看出,这个算法就是将这一个个区间的和全部加起来,效率是log(n).
设节点编号为x,那么这个节点管辖的区间为2^k(其中k为x二进制末尾0的个数)个元素。因为这个区间最后一个元素必然为Ax,
所以很明显:C[n] = A[n – 2^k + 1]+ ... + A[n]
Solution:
/*solution: TreeArray          O(n) = log(n);*/class NumArray {    int length = 0;    int[] tree;    int[] nums;        public NumArray(int[] nums) {        this.nums = nums;        length = nums.length;        tree = new int[length + 1];        tree[0] = 0;        //initial the Tree Array        for(int i = 1;i<=length;i++){            int count = lowBit(i);            int sum = 0;            while(count > 0){                sum += nums[i - count];                count--;            }            tree[i] = sum;        }    }        public void update(int i, int val) {        int gap = val - nums[i];        nums[i] = val;        int count = i + 1;                while(count <= length){            tree[count] += gap;            count += lowBit(count);        }    }        public int sumRange(int i, int j) {        return sum(j + 1) - sum(i);    }    //calculate the interval contained by the tree[i]    public int lowBit(int i){        return i & (-i);    }    //calculate the sun of interval that starts with 0 and end with index    public int sum(int i){        int result = 0;        int current = i;        while(current > 0){            result += tree[current];            current -= lowBit(current);        }        return result;    }}/** * Your NumArray object will be instantiated and called as such: * NumArray obj = new NumArray(nums); * obj.update(i,val); * int param_2 = obj.sumRange(i,j); */