Algorithm

Maximum Width of Binary Tree

Trees Pattern

Maximum Width of Binary Tree

The width of a level is the distance from its leftmost node to its rightmost node, counting the missing positions in between as if they were nodes — as though the level were a full row and only some seats were occupied. Given the root, return the largest width over all levels. Trailing and leading gaps do not count, only the span between the two outermost real nodes.

CONSTRAINTS
  • The number of nodes in the tree is in the range [1, 3000]
  • -100 <= Node.val <= 100
  • Gaps between the outermost nodes of a level count toward its width
  • The answer is guaranteed to fit in a 32-bit signed integer
EXAMPLE 1
Input: root = [1,3,2,5,3,null,9]
Output: 4
The bottom level holds 5, 3 and 9, but 9 sits one seat further right than the missing child of 2. Spanning from 5 to 9 covers four seats, one of which is empty.
EXAMPLE 2
Input: root = [1,3,2,5]
Output: 2
The bottom level contains only 5, so its width is 1. The widest level is the middle one, holding 3 and 2 side by side.
EXAMPLE 3
Input: root = [1,3,2,5,null,null,9,6,null,null,7]
Output: 8
The bottom level holds just 6 and 7, yet they sit at the far outer edges of a row with room for eight, so almost every counted seat is empty. Counting nodes would give 2 and miss the point entirely.
EXAMPLE 4
Input: root = [1]
Output: 1
A single node spans one seat. Width is never zero for a non-empty tree.
Do the gaps really count?
Yes, and that is the whole problem. Counting only real nodes turns this into a trivial exercise and gives wrong answers on sparse levels.
Do gaps outside the outermost nodes count?
No. The measurement runs from the leftmost real node to the rightmost real node, so empty seats beyond either end are ignored.
Can the position numbers get too large?
In principle yes — they double each level, so a 3000-deep tree would need astronomically large numbers. In practice you rebase them per level, which keeps them small. Worth raising in an interview even in languages with big integers.
Is a depth-first solution possible?
Yes: record the first position seen at each depth, then for every node compare its position against that. Breadth-first is more natural because each level's two extremes arrive next to each other.

The word "width" is doing something unusual here. It is not how many nodes a level holds — it is how far apart its two outermost nodes are, with the empty seats between them counted. So a level containing two nodes can have a width of eight if those nodes sit at opposite edges of the row.

That immediately rules out the obvious approach. The level-by-level walk from Binary Tree Level Order Traversal gives us each level's nodes, but the missing children were simply skipped when enqueueing, so by the time a level is assembled all information about where the holes were is gone. We need to know each node's horizontal position, not just its membership in a level.

Give every seat a number

Imagine the tree drawn as a full, gapless row at each depth: depth 0 has one seat, depth 1 has two, depth 2 has four, and depth d has 2^d. Number them so that positions relate simply between parent and child. Give the root position 0; then for a node at position i, put its left child at 2i and its right child at 2i + 1.

This numbering is worth a moment's justification rather than acceptance. Each level's row is twice as long as the one above, and every parent owns exactly two consecutive seats in the row below — the parent at position 0 owns child seats 0 and 1, position 1 owns 2 and 3, position 2 owns 4 and 5. Doubling the parent's index lands on the first of its two owned seats, and adding one lands on the second. So the scheme is exactly "which seat would this node occupy if the level were completely full", which is precisely the coordinate the problem's definition needs. (It is the same indexing that stores a binary heap in a flat array.)

Now the width of a level is arithmetic on positions, and gaps take care of themselves: rightmost position - leftmost position + 1. Nothing needs to know how many nodes are missing, because their seats were already counted by the subtraction.

python
best, queue = 0, deque([(root, 0)])          # each entry: a node and its seat number
while queue:
    n = len(queue)
    _, first = queue[0]                       # leftmost seat on this level
    last = first
    for _ in range(n):
        node, pos = queue.popleft()
        last = pos                            # the final one seen is the rightmost
        pos -= first                          # rebase, so seats start from 0 again
        if node.left:  queue.append((node.left,  2 * pos))
        if node.right: queue.append((node.right, 2 * pos + 1))
    best = max(best, last - first + 1)
return best
Crucial Notepositions double at every level, so on a 3000-deep chain a raw position would be a number with about 900 digits — in most languages that silently overflows to garbage long before then. The rebasing line fixes it: since only differences within a level matter, subtracting the level's leftmost position before computing children keeps every number small while leaving all differences untouched. This is a general trick worth remembering — when only relative values matter, subtract a common offset to keep the absolute values in range.

The other detail is that the leftmost node of a level is simply the first one dequeued and the rightmost is the last, which holds because the queue preserves left-to-right order throughout. No sorting or scanning is needed to find the extremes.

Worked example:root 1, children 3 and 2; 3 has children 5 and 3; 2 has only a right child 9
- Level 0: queue holds (1, 0). first = last = 0, width 0 - 0 + 1 = 1. Rebased position of 1 is 0, so its children get seats 0 and 1.
- Level 1: queue holds (3, 0) and (2, 1). first = 0, last = 1, width 2. Node 3 rebases to 0, so its children take 0 and 1. Node 2 rebases to 1; it has no left child, so seat 2 stays empty, and its right child 9 takes seat 3.
- Level 2: queue holds (5, 0), (3, 1) and (9, 3). first = 0, last = 3, width 3 - 0 + 1 = 4 — three nodes, one empty seat at position 2, counted.
- Answer: 4.

The empty seat at position 2 was never enqueued and was never counted explicitly. It was accounted for automatically, because 9's seat number carried the information that something was skipped to its left.

Cost, and the idea to keep

Every node is enqueued and dequeued once, doing constant work: O(N) time, O(W) space for the queue. The positions add a constant per entry.

The transferable move is the one that made the gaps computable: when a problem cares about where things would be rather than what is present, stop tracking the items and start tracking coordinates. Assigning each node a position turned "how many holes are in this level" — a question about absences, which are hard to enumerate — into a subtraction between two present nodes. The same reframing solves Vertical Order Traversal, where each node gets a horizontal coordinate (left child at x - 1, right child at x + 1) so that nodes from different subtrees can be grouped by column. Coordinates let you talk about structure that is not there.

Interactive Strategy Visualization

Max Width Calculation

Tracing Indices including Nulls

1idx:12idx:23idx:34idx:4idx:5idx:67idx:7

Calculation Step

Start at Root (Index 1). Width: 1

The width is the difference between the indices of the last and first non-null nodes, plus one.
Null nodes count towards index!

Strategy

Focus on the recursive nature of trees: solve for subtrees and combine results at the root.

"Divide and Conquer: Subproblem → Recurrence → Result"

O(N) Time · O(W) Space Position-Indexed BFS
Same With Per-Level Rebasing To Avoid Overflow