Fenwick Tree
Suppose A is an array of length n. A Fenwick tree, or a Binary Indexed Tree, is a data structure that can:
- be created in \(O(n)\) time;
- update or retrieve the value of an element of A in \(O(\log n)\) time;
- find a range sum in \(O(\log n)\) time.
Description
A Fenwick tree is implemented as a flat array where each element is equal to the sum of numbers in a certain range. The following image shows a possible interpretation of the Fenwick tree as a tree. The nodes of the tree show the ranges they cover.
Each element contains the sum of the values since its left sibling (or since zero if there are no left siblings). A prefix sum can be calculated by adding the value of the element and all its left siblings. Incrementing an element requires incrementing all the elements in the upward chain to the root.
Implementation
The left sibling and the parent of a node can be found by simple bitwise operations:
Hence the tree can be implemented as a flat array (indexing starts at 1):
These two methods are all we need to solve the problem from the previous posts:
You are given an integer array nums and you have to return a new counts array. The counts array has the property where counts[i] is the number of smaller elements to the right of nums[i].
Here is how we solve it in \(O(n \log n)\) time with a Fenwick tree:
- Sort the numbers and find each number’s rank.
- Go through numbers from right to left, insert each number’s rank into the tree, and compute the sum of all smaller ranks.
That’s it! An efficient solution in 25 lines of code.
There are more things that a Fenwick tree can do:
- initialize in \(O(n)\) time
- update an element in \(O(\log n)\) time.
Updating an element can be done by adding new value minus current value.
- retrieve an element in \(O(\log n)\) time.
To get the value of an element, we subtract all of its children. Alternatively, we could just store the original array, taking up additional \(O(n)\) memory, but retrieving elements in \(O(1)\) time.
In the next post, I’ll introduce the heap data structure.