Maximum Width of Binary Tree
Max width across levels, counting null gaps between a level's endpoints.
Open on LeetCode ↗Intuition
Give every node a heap index: root 1, children 2i and 2i+1. Width of a level = last index − first index + 1, regardless of what's missing in between. BFS with (node, index) pairs and compare per level.
Give every node a heap-style index — children of i are 2i and 2i+1 — and a level's width is last - first + 1, gaps included. The normalisation step (subtracting the level's first index) is what prevents those indices from doubling into overflow on deep trees.
Approach
Heap-style numbering
Indices encode positions in the imaginary complete tree, so gaps count themselves — no null-filling needed.
BFS by level
For each level, width = index(last) − index(first) + 1. Track the max.
Normalize to prevent overflow
Subtract the level's first index when enqueuing children — keeps numbers small (crucial in fixed-width languages, tidy anywhere).
Solution & live demo
Common pitfalls
Not normalising indices per level
if node.left: q.append((node.left, 2 * i))
i -= first if node.left: q.append((node.left, 2 * i))
Indices double each level, so a 3,000-deep skewed tree produces astronomically large values — instant overflow in C++/Java and slow big-int arithmetic in Python. Subtracting the level's first index keeps them small while preserving differences.
Counting nodes instead of measuring index span
best = max(best, len(q))
best = max(best, i - first + 1)
Width counts the null gaps between the outermost nodes, not just the nodes present. A level with two nodes at indices 0 and 7 has width 8, not 2.
Reading the level's first index after the loop
for _ in range(len(q)):
node, i = q.popleft()
first = ifirst = q[0][1] for _ in range(len(q)):
By the end of the loop the queue holds the next level, so first must be captured before any popping starts. Reading it late normalises against the wrong baseline.
Edge cases
Indices double per level; normalization keeps them bounded by the level's span.
Width 1.