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) -> 9 update(1, 2) sumRange(0, 2) -> 8
Note:
- The array is only modifiable by the update function.
- 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);
*/