Binary Tree Level Order Traversal

MediumTrees · BFS (Level Order)🧩 Tree BFS (Level Order)LeetCode #102 ↗Updated

Problem

Given the root of a binary tree, return its node values grouped level by level: one list per depth, starting at the root, with each level read from left to right.
Input[3,9,20,null,null,15,7]Output[[3],[9,20],[15,7]]
Input[1]Output[[1]]
Input[]Output[]

0 ≤ nodes ≤ 2000  ·  -1000 ≤ Node.val ≤ 1000

Try it yourself

Java
class Solution {
    public List<List<Integer>> levelOrder(TreeNode root) {
        
    }
}
Your code is saved in this browser.Submit on LeetCode ↗
Key insight
A FIFO queue hands nodes out in exactly level order. Snapshot queue.size() at the start of each round — that many polls is precisely one level, while the children you enqueue form the next one.
PatternTree BFS (Level Order)

Instinct The answer talks about levels, rows, depth order, "closest to the root" or what you see from a side? Queue the tree and process it one level at a time.

Memory hack Freeze the size, drain the row - read n = queue.size() before the loop and one level never bleeds into the next.

Open the Tree BFS (Level Order) guide →

Approaches

Brute ForceHeight + DFS per Level

Time O(n · h)Space O(h)

Compute the height h, then for every depth d run a fresh DFS that only records nodes exactly d edges below the root (left before right, so order is correct). Upper levels are re-walked for every deeper level.

Java
public List<List<Integer>> levelOrder(TreeNode root) {
    List<List<Integer>> res = new ArrayList<>();
    int h = height(root);
    for (int d = 0; d < h; d++) {
        List<Integer> level = new ArrayList<>();
        collect(root, d, level);
        res.add(level);
    }
    return res;
}
private int height(TreeNode node) {
    return node == null ? 0 : 1 + Math.max(height(node.left), height(node.right));
}
private void collect(TreeNode node, int d, List<Integer> level) {
    if (node == null) return;
    if (d == 0) {
        level.add(node.val);
        return;
    }
    collect(node.left, d - 1, level);
    collect(node.right, d - 1, level);
}

Simple, but a skewed tree (h = n) makes it O(n²).

At a glance

LevelApproachTimeSpace
Brute ForceHeight + DFS per LevelO(n · h)O(h)
BetterSingle DFS with Depth IndexO(n)O(h)
OptimalBFS with Queue (Level-Size Snapshot)O(n)O(w)
Common pitfalls
  • Using queue.size() as the loop bound while adding children — snapshot it first.
  • Forgetting the root == null case → NPE on the first poll.
  • ArrayDeque rejects null — never enqueue missing children.
Interview tips
  • Name it: “level order = BFS with a queue”, then explain the size snapshot.
  • Mention the DFS-with-depth alternative and its O(h) vs O(w) space trade-off.
  • Walk through the example tree, showing the queue contents after each level.
Pattern
BFS level-by-level (queue + size snapshot) → any question about depths, levels, or the nearest/first node per level.
My notes saved in this browser