Trees · Binary Tree Views

Binary Tree Level View

Running a level-order (BFS) traversal and picking out one specific piece of information per level - the first node, the last node, or the level's index span - rather than collecting every node.

  • 7 min read
  • 11 practice questions
  • 7 graded problems
On this page
  1. Description
  2. The approach
  3. A second flavor: DFS with an explicit depth
  4. Measuring width with position indices
  5. Where you'll see it
  6. Which tool for which job?
  7. Common mistakes
  8. Check yourself
  9. Key takeaways
  10. Quick revise
  11. Practice

Description

Level views answer questions about a tree one row at a time. Print it level by level, zigzag between directions, show what's visible from the left or right side, or find the widest level. Breadth-first search with a queue handles all of them. Snapshot the queue's size at the start of each level, and the loop knows exactly where one level ends.

We'll go from simple to more technical:

  1. The pattern: BFS with a level-size snapshot.
  2. A second flavor: DFS with an explicit depth (left and right views).
  3. Measuring width with position indices.
  4. The bugs that blur levels together, and BFS versus DFS memory.

The approach

A recursive DFS jumps between levels all the time, so it has no natural moment when "this level is done". A breadth-first walk with a queue visits the tree level by level. The one trick: at the start of each level, the queue holds exactly that level's nodes. Read the queue's size then, and process exactly that many nodes. Their children, added along the way, wait for the next round.

right

7

3

9

2

4

8

11

right

7

3

9

2

4

8

11

LevelQueue at the startFirst node (left view)Last node (right view)
0777
13, 939
22, 8, 11211
3444

The right view is 7, 9, 11, 4. Notice that 4 hangs on the left side but is still the rightmost node on its level.

Java

Queue<TreeNode> queue = new ArrayDeque<>();
if (root != null) queue.offer(root);
while (!queue.isEmpty()) {
    int size = queue.size();          // exactly the nodes at the current level
    for (int i = 0; i < size; i++) {
        TreeNode node = queue.poll();
        if (i == 0)        { /* leftmost of this level - left view */ }
        if (i == size - 1) { /* rightmost of this level - right view */ }
        if (node.left != null) queue.offer(node.left);
        if (node.right != null) queue.offer(node.right);
    }
}

Python

from collections import deque

queue = deque([root] if root else [])
while queue:
    size = len(queue)                   # exactly the nodes at the current level
    for i in range(size):
        node = queue.popleft()
        if i == 0:
            pass                        # leftmost of this level - left view
        if i == size - 1:
            pass                        # rightmost of this level - right view
        if node.left:
            queue.append(node.left)
        if node.right:
            queue.append(node.right)

Each question here is this loop plus one choice of what to keep per level. That's the first node, the last, the whole level (reversed every other time for zigzag), or the span of positions.

A second flavor: DFS with an explicit depth

Level questions don't strictly need a queue. A DFS can carry the current depth, and the first node it reaches at each new depth is the view from one side. It just has to visit that side's child first:

Java

void rightView(TreeNode node, int depth, List<Integer> out) {
    if (node == null) return;
    if (depth == out.size()) out.add(node.val);   // first node reached at this depth
    rightView(node.right, depth + 1, out);          // right first, so the rightmost node wins
    rightView(node.left, depth + 1, out);
}

Python

def right_view(node: TreeNode | None, depth: int, out: list[int]) -> None:
    if node is None:
        return
    if depth == len(out):
        out.append(node.val)                  # first node reached at this depth
    right_view(node.right, depth + 1, out)    # right first, so the rightmost node wins
    right_view(node.left, depth + 1, out)

On the tree above it also returns 7, 9, 11, 4. But DFS order isn't level order. Questions that need true top-to-bottom order, like the top and bottom views (see Binary Tree Vertical Ordering), need explicit depth tracking or BFS.

Measuring width with position indices

The maximum width counts gaps too. Number the nodes like a heap: the children of position i are 2i + 1 and 2i + 2. A level's width is its last position minus its first, plus one. In the tree above, level 2 has a gap where 3's right child would be, so its width is 4. Raw positions double every level, though, and overflow on deep trees. So the queue carries (node, position) pairs, and each node's position is reduced by its level's first position before its children's are computed. No width changes, and the numbers stay small:

Java

long idx = entry.index - first;                 // normalized: 0 .. width - 1
if (node.left != null)  queue.offer(new Entry(node.left,  2 * idx + 1));
if (node.right != null) queue.offer(new Entry(node.right, 2 * idx + 2));

Python

idx = index - first                             # normalized: 0 .. width - 1
if node.left:
    queue.append((node.left, 2 * idx + 1))
if node.right:
    queue.append((node.right, 2 * idx + 2))

Where you'll see it

Drawing an org chart one row at a time uses exactly this loop. So does working out how wide a layout gets at its widest row.

Which tool for which job?

You needUse
Nodes level by level (or zigzag)BFS, snapshotting the queue size per level
Left or right viewBFS (first or last per level), or DFS recording the first node per depth
Top or bottom viewBFS with a column per node (the shallowest or last per column)
The widest level, counting gapsBFS with position indices, normalized per level
Little memory to spareBFS needs O(width), DFS O(height): pick by the tree's shape

Common mistakes

MistakeWhat happensDo this instead
Re-reading queue.size() in the looplevels mergeread the size once per level
Top view by DFS without deptha deeper node wins a columnBFS, or keep the shallowest depth per column
Raw position indices on deep treesthey double each level (overflow, or huge ints)subtract the level's first index
list.pop(0) as a Python queueeach pop shifts the list - O(n^2)collections.deque
Reversing a zigzag level in place in the queuelater levels come out in the wrong orderreverse only the output list

Check yourself

Try to answer before opening each one - recalling beats re-reading.

1. A level-order loop is written for (int i = 0; i < queue.size(); i++). What does it print for the tree [1, 2, 3]?

Show answer

1 2 on the first line and 3 on the second. The size is re-read every time round. After 1 is taken out, its children 2 and 3 are in the queue, so the loop goes on and pulls 2 into the first "level". Reading the size once, before the loop, fixes the level at one node.

2. A right-view DFS records the first node per depth but visits the left child first. What does it return for [1, 2, 3]?

Show answer

1 2, which is the left view. The first node reached at each depth is from whichever side is visited first. The rule is right; the visiting order decides which side it shows.

3. Why does maximum width subtract each level's first position before computing the children's positions?

Show answer

Raw positions double every level and overflow on deep trees. Width only depends on differences within a level, so subtracting the first position changes no width and keeps the numbers small.

Key takeaways

  • Read the queue's size before each level's loop. It's the only thing that marks where a level ends.
  • Level questions differ only in what they keep per level: the first node, the last, the whole level, or the span of positions.
  • A DFS with an explicit depth can find the side views in O(height) space, but its order isn't level order.
  • Heap-style positions measure width including gaps. Normalize them per level.

Quick revise

The whole skill on one page, for the night before an interview.

Everything from the lesson and the deep dive on one page. Skim it before practice or an interview, and open the full lesson for anything that doesn't ring a bell.

Pick the tool

You needUse
Levels / zigzagBFS + size snapshot
Left / right viewfirst / last per level
Top / bottom viewBFS with columns
Widthnormalized position indices
MemoryDFS for bushy, BFS for deep

Snippets worth knowing by heart

Java

Deque<TreeNode> q = new ArrayDeque<>(List.of(root));
while (!q.isEmpty()) {
    int size = q.size();                         // this level, read once
    for (int i = 0; i < size; i++) {
        TreeNode n = q.poll();
        if (i == size - 1) rightView.add(n.val); // last in the level
        if (n.left != null) q.add(n.left);
        if (n.right != null) q.add(n.right);
    }
}

Python

from collections import deque
best, q = 0, deque([(root, 0)])
while q:
    first = q[0][1]
    for _ in range(len(q)):                      # range() reads the length once
        node, idx = q.popleft()
        idx -= first                             # normalize per level
        if node.left:
            q.append((node.left, 2 * idx))
        if node.right:
            q.append((node.right, 2 * idx + 1))
    best = max(best, idx + 1)

The traps

  • Re-reading the size: the queue grows during the loop and levels merge. Read the size once per level.
  • DFS top view without depth: a deeper node wins a column. Use BFS, or keep the shallowest depth.
  • Raw indices on deep trees: positions double each level and overflow. Subtract the level's first index.
  • list.pop(0): each pop shifts the list, so BFS is O(n^2). Use collections.deque.
  • Reversing the queue for zigzag: later levels come out in the wrong order. Reverse only the output list.

Staff-level points, one line each

  • Snapshot: [[1], [2, 3], [4, 5, 6]]; re-reading size(): [[1, 2, 3], [4, 5], [6]].
  • Perfect 1,023 nodes: BFS peak 512, DFS 10; chain of 1,000: BFS 1, DFS 1,000.
  • DFS top view gave [2, 1, 5, 6]; BFS gave [2, 1, 3, 6].
  • 5,000 right steps: a 5,000-bit raw index - normalize.
  • list.pop(0) over 5x slower than deque.popleft on 200,000 items.

Say it in an interview

  • "I snapshot the queue size, so each iteration of the outer loop is exactly one level."
  • "BFS holds a level, DFS holds a path - I pick by the tree's shape."
  • "For the top view I need the shallowest node per column, which BFS gives me."
  • "I normalize position indices per level so they don't blow up."

Practice

This skill comes with 11 multiple-choice questions that tell you which misconception a wrong answer reveals and 7 graded problems. Your answers are graded and your mastery is tracked, so you'll know when the skill holds up. Running code and saving progress need a free account.

Practice Binary Tree Level View free

Left View of Binary Tree

MediumProCoding problemJava · Python

Given the root of a binary tree, return the values visible when looking at the tree from the left side - the leftmost node at each level, top to bottom.

The full statement, the examples and the hidden test suite are part of AI Proof Engineers Pro.

Right View of Binary Tree

MediumProCoding problemJava · Python

Given the root of a binary tree, return the values visible when looking at the tree from the right side - the rightmost node at each level, top to bottom.

The full statement, the examples and the hidden test suite are part of AI Proof Engineers Pro.

Top View of Binary Tree

MediumProCoding problemJava · Python

Given the root of a binary tree, return the values visible when looking at the tree from directly above: for each horizontal distance from the root (left child: -1, right child: +1), the first node encountered there in a top-to-bottom, left-to-right scan, ordered left to right…

The full statement, the examples and the hidden test suite are part of AI Proof Engineers Pro.

Bottom View of Binary Tree

MediumProCoding problemJava · Python

Given the root of a binary tree, return the values visible when looking at the tree from directly below: for each horizontal distance from the root, the last node encountered there in a top-to-bottom, left-to-right scan, ordered left to right by horizontal distance.

The full statement, the examples and the hidden test suite are part of AI Proof Engineers Pro.

Maximum Width of Binary Tree

MediumProCoding problemJava · Python

Given the root of a binary tree, return its maximum width: the largest number of nodes that would exist between (and including) the leftmost and rightmost non-null nodes at any level, if the tree were laid out as a complete binary tree (using the standard heap-array position…

The full statement, the examples and the hidden test suite are part of AI Proof Engineers Pro.

Binary Tree Level Order Traversal

MediumProCoding problemJava · Python

Given the root of a binary tree, return its level-order traversal: a list of levels, each level being the values of its nodes left to right.

The full statement, the examples and the hidden test suite are part of AI Proof Engineers Pro.

Binary Tree Zigzag Level Order Traversal

MediumProCoding problemJava · Python

Given the root of a binary tree, return its level-order traversal, alternating direction each level: the first level left to right, the second right to left, the third left to right, and so on.

The full statement, the examples and the hidden test suite are part of AI Proof Engineers Pro.

Practice Binary Tree Level View free

No card needed. Lessons, practice questions and easy problems are free forever.

Free plan, no card · 7-day Pro trial · Cancel anytime