Fenwick树状数组

基本思想:

  树状数组是用来解决在数组元素动态变化的情况下,高效的计算子数组和的一种数据结构,其更新效率和计算和的效率均为O(logn),和普通的sum数组不同的是,虽然sum数组计算子数组和的效率为O(1),但是在面对数组元素动态变化的情况下,其更新效率为O(n)。Fenwick数组的更新方式如下图:

  首先需要一个辅助函数lowbit,用于计算最低位所在的位置,比如二进制110,那么它返回的是二进制10,这个函数利用补码的特性x&(-x)即可实现。有了这个函数,就可以实现数组的更新与查询。我们需要两个数组vec和tree,vec用于存储原始数据,tree是树状数组。对于更新操作,记录下该位置和原始数据之差diff,然后i += lowbit(i)进行更新。对于i到j之间的子数组之和,计算0到j和0到i两部分的和相减即可,而对于0到i之和,从第i个数开始i -= lowbit(i),并将tree[i]相加即可。代码如下,即Leetcode 307答案

 1 class NumArray {
 2 public:
 3     NumArray(vector<int> nums) {
 4         vec = vector<int>(nums.size(),0);
 5         tree = vector<int>(nums.size()+1);
 6         for(int i = 0;i != nums.size();++i){
 7             update(i,nums[i]);
 8             vec[i] = nums[i];
 9         }
10     }
11     
12     void update(int i, int val) {
13         int diff = val-vec[i];
14         vec[i] = val;
15         int index = i+1;
16         while(index < tree.size()){
17             tree[index] += diff;
18             index += lowBit(index);
19         }
20     }
21     
22     int sumRange(int i, int j) {
23         return getSum(j+1)-getSum(i);
24     }
25 private:
26     vector<int> tree;
27     vector<int> vec;
28     int lowBit(int x){
29         return x&(-x);
30     }
31     int getSum(int x){
32         int result = 0;
33         while(x > 0){
34             result += tree[x];
35             x -= lowBit(x);
36         }
37         return result;
38     }
39 };

参考资料:

   https://www.youtube.com/watch?v=WbafSgetDDk&t=748s

猜你喜欢

转载自www.cnblogs.com/haoweizh/p/10211849.html