Binary Tree Level Order Traversal
Use a queue, and split it into rounds. At the start of each round, take size = q.size() before pushing any children. Those size nodes are exactly one row. Pop that many, push their children to the back, and the next round starts with the next row.
The queue holds exactly one row when a round starts, so popping size nodes takes out that whole row and nothing from the row below it.
Problem
You are given the root of a binary tree. Return the node values one row at a time: first the root's row, then the row below it, and so on. Inside each row, read the nodes from left to right.
Each row becomes one inner list in the answer. An empty tree gives an empty answer.
The root of a binary tree. It can be empty (null).
In the examples, a tree is written in level order: the root first, then each row left to right. A null marks a missing child, so [3, 9, 20, null, null, 15, 7] means 9 and 20 are the root's children, and 9 has no children.
A list of rows. The first list is the root's row, the next list holds its children, and so on. Each row is read left to right.
Row 0 is 3. Row 1 is its children 9 and 20. Row 2 is 15 and 7, the children of 20 (9 has none).
A single node is one row.
No nodes, so no rows.
- • The number of nodes in the tree is in the range [0, 2000].
- • −1000 ≤ Node.val ≤ 1000
First, think yourself
Before opening any solution, try to answer these on paper. Use hints only when stuck — each hint is counted.
- 1.
Is a row of the tree a set of nodes at the same depth? What order would I need to visit nodes in to print one row at a time?
- 2.
Does depth-first search naturally visit the nodes row by row, or does breadth-first search?
- 3.
If I visit a node and then its children, how would I know where one row stops and the next row starts?
- 4.
Could I walk the whole tree once for each row and keep only the nodes at that depth? What would that cost?
- 5.
When one row is about to start, how many nodes belong to it? Can I know that before I pop any of them?
Brute force approach
Optimized approach
Why does this algorithm work?
Dry run
All approaches compared
| Approach | Idea | Time | Space |
|---|---|---|---|
| Brute Force | For each depth d, walk the whole tree and keep the nodes at depth d | O(N · H) | O(H) |
| Optimal | Queue-based BFS; take size = q.size() at the start of each round and pop exactly that many | O(N) | O(N) |
Why does this belong to this pattern?
- “level by level”Rows are depths. A question about rows is a breadth-first question, not a path question.
- “left to right inside each level”A queue gives this order for free, because children are pushed left, then right.
- “return a list of lists”One inner list per row, so the number of rounds equals the number of rows.
The question asks for rows, not paths, so Tree BFS is the right family. The key rule is take size at the start of each round and pop exactly that many. The row below always sits behind the current row in the queue, so the snapshot is the only thing that marks the boundary. Binary Tree Level Order II, N-ary Level Order and Zigzag all reuse this same loop.
Don't make this mistake
Pattern confusion: the loop condition is checked after every pop, and each pop can push two children. The queue grows with the row below, so the loop keeps going past this row's boundary and the next row bleeds into this one. On [3, 9, 20, null, null, 15, 7] the live version gives [[3, 9], [20, 15], [7]]. After 3 is popped, the queue holds [9, 20] (size 2), so the loop also pops 9 and files it under row 0.
A null pointer goes into the queue, and the next pop reads ->val of nullptr and crashes. Node 9 in the example has no children, so the wrong version queues two nulls right behind 20.
An empty tree must return []. Without the check, a null root sits in the queue and crashes on its first pop.
Want to implement this?
Write it yourself on LeetCode, then come back and compare your code with the solutions above.
Open coding workspaceHow this concept connects to System Design & C++ Systems
Top engineering interviews test whether you understand how algorithms like Tree BFS translate into production architectures and low-level memory mechanics.
Foundations: Object-Oriented Principles in C++23
Class invariants, pure virtual interfaces, and RAII smart pointers.
Food Delivery System (Zomato Architecture)
Real-world machine coding application of algorithms and design patterns.
Pointers vs References Deep Dive
Pointer arithmetic and memory layout under the hood.
Virtual Method Table (vtable) & Memory Layout
Polymorphism, vptr overhead, and multiple inheritance in memory.