Fenwick Tree
A Fenwick tree or binary indexed tree is a data structure that can efficiently update elements and calculate prefix sums in a table of numbers. This structure was proposed by Peter Fenwick in 1994 to improve the efficiency of arithmetic coding compression algorithms.
二叉搜索树(BIT)可以用于维护和查询区间信息,它可以在O(logn)的时间复杂度下求出区间和。
[一棵Fenwick树]!(https://upload.wikimedia.org/wikipedia/commons/thumb/d/dc/BITDemo.gif/300px-BITDemo.gif)
在建立和更新数组时,从左向右,从叶子节点向根节点依次求和。 在查询区间和时,从右向左,求出前缀和的差值。
下面是BIT的C和C++实现。
#define LSB(i) ((i) & -(i)) // zeroes all the bits except the least significant one
int A[SIZE];
int sum(int i) // Returns the sum from index 1 to i
{
int sum = 0;
while (i > 0)
sum += A[i], i -= LSB(i);
return sum;
}
void add(int i, int k) // Adds k to element with index i
{
while (i < SIZE)
A[i] += k, i += LSB(i);
}
class fenwickTree{
vector<int> sums; //parital sum
static inline int lowbit(int x) {return x & (-x);}
public:
//index start from 1
fenwickTree(int n):sums(n+1, 0){}
void update(int i, int delta){
while(i < sums.size()){
sums[i] += delta;
i += lowbit(i); //remove the lowest bit 1
}
}
int query(int i) const {
int sum = 0;
while(i > 0){
sum += sums[i];
i -= lowbit(i);
}
return sum;
}
};
307. Range Sum Query - Mutable
Medium
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.
class NumArray {
fenwickTree ft;
vector<int> nums_;
public:
NumArray(vector<int>& nums):ft(nums.size() + 1),nums_(nums.size(), 0) {
for(int i = 0; i < nums.size(); i++){
ft.update(i+1, nums[i]);
nums_[i] = nums[i];
}
}
void update(int i, int val) {
ft.update(i + 1, val - nums_[i]);
nums_[i] = val;
}
int sumRange(int i, int j) {
return ft.query(j+1) - ft.query(i);
}
};
/**
* 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);
*/
测试一下
Success
Details
Runtime: 36 ms, faster than 92.57% of C++ online submissions for Range Sum Query - Mutable.
Memory Usage: 19.3 MB, less than 39.95% of C++ online submissions for Range Sum Query - Mutable.