树状数组(binary index tree)
概述
修改和查询复杂度为log(n)的数据结构,所有奇数位的数和原数位置相同,偶数位置是原数组若干位置的和。
假如原数组A(a1, a2, a3, a4 ...),和其对应的树状数组C(c1, c2, c3, c4 ...)有如下关系:
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
数组的有几个位置组成由坐标的最低位决定,所谓的最低位,就是二进制数的最右边的一个1开始,加上后面的0(如果有的话)组成的数字,例如1到8的最低位如下面所。
坐标 二进制 最低位
1 0001 1
2 0010 2
3 0011 1
4 0100 4
5 0101 1
6 0110 2
7 0111 1
8 1000 8
...
最低位的计算方法有两种,一种是x&(x^(x–1))
,另一种是利用补码特性x&-x。
找节点的父节点 ;
public class NumArray { int[] nums; int[] bit; int n; public NumArray(int[] nums) { this.nums = nums; n = nums.length; bit = new int[n + 1]; for (int i = 0; i < n; i++) { init(i, nums[i]); } } public void init(int i, int val) { i++; while (i <= n) { bit[i] += val; i += (i & -i); } } public void update(int i, int val) { int diff = val - nums[i]; nums[i] = val; init(i, diff); } public int getSum(int i) { int res = 0; i++; while (i > 0) { res += bit[i]; i -= (i & -i); } return res; } public int sumRange(int i, int j) { return getSum(j) - getSum(i-1); } }