Skip to main content

Fenwick Tree

This page provides links to solutions that use the Fenwick Tree data structure.

Overview

The Fenwick Tree, also known as the Binary Indexed Tree, is a data structure that can perform range operations such as finding the total, minimum, or maximum value in O(log N)\text{O(log N)} time.

It can also perform point updates in O(log N)\text{O(log N)} time. However, it does not support range updates; in such cases, a segment tree should be used instead. Despite being called a tree, the Fenwick tree is actually stored as an array of elements.

To create a Fenwick tree, you need two functions called Get Parent and Get Child. These functions help you determine which index to update next when you add or change an element in the Fenwick tree.

Get Parent Function

Get Parent function generates the parent index by adding 11 to the last set bit from the right.

Let's calculate parent of 66 which is represented as 01100110 in binary format. The first set bit from right is in 2nd2^{nd} position, so we add 11 to that position

0110+0010=10000110 + 0010 = 1000

Therefore, the parent of 66 is 88.

public int getParent(int index) {
return index + (i & -i);
}

Get Child Function

Similarly, Get Child function generates the child index by substracting 11 from the last set bit from the right.

Let's calculate child of 66 which is represented as 01100110 in binary format. The first set bit from right is in 2nd2^{nd} position, so we substract 11 from that position

01100010=01000110 - 0010 = 0100

Therefore, the child of 66 is 44.

public int getChild(int index) {
return index - (i & -i);
}

Build Fenwick Tree

Let's create a fenwick tree for input array

[1,3,4,13,4,44,3]\begin{bmatrix} 1, 3, 4, 13, -4, 44, -3 \end{bmatrix}

Generate a new array with a length one greater than the input array, initializing all elements to 0. Fenwick tree array after adding 1st1^{st} element

fenwick-tree-1.svg

Fenwick tree array after adding 2nd2^{nd} element

fenwick-tree-2.svg

Fenwick tree array after adding 3rd3^{rd} element

fenwick-tree-3.svg

Fenwick tree array after adding 4th4^{th} element

fenwick-tree-4.svg

Fenwick tree array after adding 5th5^{th} element

fenwick-tree-5.svg

Fenwick tree array after adding 6th6^{th} element

fenwick-tree-6.svg

Fenwick tree array after adding 7th7^{th} element

fenwick-tree-7.svg
public int[] buildFenwickTree(int[] arr) {
// create a fenwickTree array
int[] fenwickTree = new int[arr.length + 1];

// add element to fenwick tree starting from index i
for(int i = 1; i < fenwickTree.length; i++) {
add(arr[i - 1], i);
}

// return fenwick tree
return fenwickTree;
}

private void add(int element, int index) {
// adding element until end of fenwick tree is reached
while(index < fenwickTree.length) {
// add element at current index
fenwickTree[index] += element;

// get parent index of current index
index = getParent(index);
}
}

Use Fenwick Tree

The Fenwick tree we generated earlier enables range operations, particularly range sum calculations in O(logN)O(log N) time.

Let's calculate range sum from 44 to 66.

First we will start with calculate the prefix sum from 33. Starting with index 44 in the Fenwick Tree, we will add elements at each step, and move towards 00.

fenwick-tree-8.svg

Therefore prefix sum from 33 will be 2121.

info

Notice how we are starting with index 44 for calculating prefix sum from 33 as fenwick tree array start inserting elements from index 11.

Now let's calculate the prefix sum from 66.

fenwick-tree-9.svg

Therefore prefix sum from 66 will be 5858.

Now, to compute the range sum from 44 to 66, subtract the prefix sum at index 33 from the prefix sum at index 66, which gives us answer as 3737.

public int rangeSum(int from, int to) {
prefixSum(to + 1) - prefixSum(from);
}

private int prefixSum(int element, int index) {
int sum = 0;
while(index > 0) {
// add element at current index
sum += fenwickTree[index];

// get child index of current index
index = getChild(index);
}
}

Update Fenwick Tree

To update an element in a Fenwick tree, we follow a similar process as adding an element. However, instead of adding the actual element, we add a delta value.

Let's update 0th0^\text{th} index in an input array to 33.

Delta at 0th0^\text{th} index is 31=23 − 1 = 2 , so we start by adding 22 starting from 11 st index in fenwick tree.

fenwick-tree-9.svg
private int update(int newValue, int index) {
// calculate delta value
int delta = arr[index] - newValue;

// update value at index in input array to newValue
arr[index] = newValue;

// call add function
add(delta, index);
}

How to Spot These Problems

You can identify fenwick tree problems if the problem requires you to:

  • Quickly calculate the sum of elements from the start of an array up to a certain index.

Leetcode Problem Set