In this episode, we will introduce Fenwick Tree/Binary Indexed Tree, its idea and implementation and show its applications in leetcode.
Fenwick Tree is mainly designed for solving the single point update range sum problems(单点更新区间和问题).
e.g. what’s the sum between i-th and j-th element while the values of the elements are mutable.
Init the tree (include building all prefix sums) takes O(nlogn)
Update the value of an element takes O(logn)
Query the range sum takes O(logn)
Space complexity: O(n)
例子:
input:[1,2,3,4,5,6,7,8] n=8, lowbit(x)=x&(-x)
lowbit(5)=5&(-5) =0101& 1011=0001 取最低位的操作
c++版: leetcode 307. Range Sum Query – Mutable
class FenwickTree {
public:
FenwickTree(int n): sums_(n + 1, 0) {}
void update(int i, int delta) {
while (i < sums_.size()) {
sums_[i] += delta;
i += lowbit(i);
}
}
int query(int i) const {
int sum = 0;
while (i > 0) {
sum += sums_[i];
i -= lowbit(i);
}
return sum;
}
private:
static inline int lowbit(int x) {
return x & (-x); //lowbit操作顾名思义:取x的最低位
}
vector<int> sums_;
};
class NumArray{
private:
vector<int> nums_;
FenwickTree tree_;
public:
NumArray(vector<int> nums):nums_(std::move(nums)),tree_(nums_.size()){
for(int i=0;i<nums_.size();i++)
tree_.update(i+1,nums_[i]);
}
void update(int i,int val){ //第i个元素的值更新为val
tree_.update(i+1,val-nums_[i]); //增量= val-nums_[i]
nums_[i]=val;
}
int sumRange(int i,int j){
return tree_.query(j+1)-tree_.query(i);
}
};
java版:
class FenwickTree {
int sums_[];
public FenwickTree(int n) {
sums_ = new int[n + 1];
}
public void update(int i, int delta) {
while (i < sums_.length) {
sums_[i] += delta;
i += i & -i;
}
}
public int query(int i) {
int sum = 0;
while (i > 0) {
sum += sums_[i];
i -= i & -i;
}
return sum;
}
}
Python版:
class FenwickTree:
def __init__(self, n):
self._sums = [0 for _ in range(n + 1)]
def update(self, i, delta):
while i < len(self._sums):
self._sums[i] += delta
i += i & -i
def query(self, i):
s = 0
while i > 0:
s += self._sums[i]
i -= i & -i
return s