CodeMosa

Master LeetCode Patterns

AdvancedAdvanced Patterns

Fenwick Tree (Binary Indexed Tree)

Compact structure for prefix sums with O(log n) point updates and queries.

Time: O(log n) per op
Space: O(n)

What is Fenwick Tree (Binary Indexed Tree)?

#
Definition: A Fenwick Tree is a compact array-based structure that maintains prefix sums, supporting point updates and prefix queries in O(log n).

Core Idea

#

Store partial sums indexed by least-significant-one-bit; add(i, Δ) updates O(log n) nodes and prefixSum(i) aggregates O(log n) nodes.

When to Use

#

Use for dynamic prefix sums/frequencies or coordinate-compressed indices; great for inversion counts, order statistics, and 1D offline queries.

How Fenwick Tree (Binary Indexed Tree) works

#

Represent partial sums in an array where index i is responsible for the range (i - lsb(i) + 1 .. i). Updating index i adds Δ to i and then jumps by lsb(i); querying prefix(i) accumulates values while subtracting lsb(i). This exploits binary decomposition of indices.

  • Prefix sums
  • Point updates
  • Frequency counts

Fenwick Tree (Binary Indexed Tree) vs alternatives

#

Use this pattern when use for dynamic prefix sums/frequencies or coordinate-compressed indices; great for inversion counts, order statistics, and 1d offline queries.

General Recognition Cues

#
General indicators that this pattern might be applicable
  • Prefix sums
  • Point updates
  • Frequency counts
  • Order statistics
#
Curated practice sets for this pattern

Code Templates

#
Fenwick/BIT for prefix sums and frequency tables; extend to range updates via difference tricks.
class Fenwick:
    def __init__(self, n): self.n=n; self.bit=[0]*(n+1)
    def add(self, i, delta):
        i+=1
        while i<=self.n: self.bit[i]+=delta; i+=i&-i
    def sum(self, i):
        i+=1; s=0
        while i>0: s+=self.bit[i]; i-=i&-i
        return s
    def range_sum(self, l, r): return self.sum(r)-self.sum(l-1)

Pattern Variants & Approaches

#
Different methodologies and implementations for this pattern
1

Point Update + Prefix Query

#

Standard BIT for sum/frequency with O(log n) per op.

When to Use This Variant
  • Prefix sums
  • Counts
Use Case
Sum/freq
Advantages
  • Simple
  • Compact
Implementation
class Fenwick:
    def __init__(self, n): self.n=n; self.bit=[0]*(n+1)
    def add(self, i, delta):
        i+=1
        while i<=self.n: self.bit[i]+=delta; i+=i&-i
    def sum(self, i):
        i+=1; s=0
        while i>0: s+=self.bit[i]; i-=i&-i
        return s
    def range_sum(self, l, r): return self.sum(r)-self.sum(l-1)
2

Range Update via Difference

#

Use BIT on differences or two BITs to simulate range updates and queries.

When to Use This Variant
  • Range add
  • Prefix read
Use Case
Range add + prefix sum
Advantages
  • O(log n)
  • Lower memory vs segtree
Implementation
# Fenwick/BIT Range Add + Prefix/Range Sum (two BITs)
class BIT:
    def __init__(self,n): self.n=n; self.bit=[0]*(n+1)
    def add(self,i,delta):
        i+=1
        while i<=self.n:
            self.bit[i]+=delta; i+= i & -i
    def sum(self,i):
        i+=1; s=0
        while i>0:
            s+=self.bit[i]; i-= i & -i
        return s

class RangeBIT:
    def __init__(self,n): self.n=n; self.b1=BIT(n); self.b2=BIT(n)
    def _add(self,bit,i,delta): bit.add(i,delta)
    def range_add(self,l,r,delta):
        # add delta to [l,r]
        self._add(self.b1,l,delta); self._add(self.b1,r+1,-delta)
        self._add(self.b2,l,delta*(l)); self._add(self.b2,r+1,-delta*(r+1))
    def _prefix(self,x):
        # sum[0..x]
        return (x+1)*self.b1.sum(x) - self.b2.sum(x)
    def range_sum(self,l,r):
        return self._prefix(r) - (self._prefix(l-1) if l>0 else 0)
3

Fenwick vs Segment Tree

#

Trade-offs: memory and simplicity vs generality and lazy range updates

When to Use This Variant
  • Prefix sums/frequencies
  • Order statistics
Use Case
When operations are sums and point updates
Advantages
  • Simpler, lower memory than segtree
  • Fast in practice
Implementation
class Fenwick:
    def __init__(self, n): self.n=n; self.bit=[0]*(n+1)
    def add(self, i, delta):
        i+=1
        while i<=self.n: self.bit[i]+=delta; i+=i&-i
    def sum(self, i):
        i+=1; s=0
        while i>0: s+=self.bit[i]; i-=i&-i
        return s
    def range_sum(self, l, r): return self.sum(r)-self.sum(l-1)

Common Pitfalls

#
Watch out for these common mistakes
  • 1-based indexing
  • Off-by-one on ranges
  • Forgetting to compress coordinates

Example Problems

#
Classic LeetCode problems using this pattern

Complexity Analysis

#
Time Complexity
O(log n) per op

Updates/queries climb/descend by clearing or adding LSOne.

Space Complexity
O(n)

One array of length n+1.

Ready to test your knowledge?

Test your pattern recognition with interactive questions