Binary Tree Level Order Traversal
Given the root of a binary tree, return its node values grouped by depth: first a list with the root's value, then a list with the values on the next level, and so on down to the deepest level. Within each level, list the values from left to right.
If the tree is empty, return an empty list.
Trees are written in level order, with null marking a missing child. For example, [5,2,8,null,4,7] is a root 5 whose left child 2 has only a right child 4, and whose right child 8 has a left child 7.
Example 1
Example 2
Example 3
Constraints
- The number of nodes is between 0 and 2000.
-1000 <= Node.val <= 1000
Pattern Path · Trees: BFS · problem 92 of 169
Start simple
Compute each node's depth with DFS and bucket values by depth (also O(n)); a naive version that re-walks the tree once per level costs O(n · h).
The key idea
Breadth-first search explores nodes in order of their distance from the root, which is exactly the grouping we want. Use a queue and process it one level at a time.
The invariant is: at the start of each round, the queue holds every node of the current level, in left-to-right order, and nothing else. So read size = len(queue), pop exactly size nodes, append their values to a new list, and push each popped node's left child and then right child. The children pushed this round form the next level, still in left-to-right order because parents were processed left to right and each pushes left before right.
When the queue is empty, every level has been emitted. Each node is pushed and popped once, so the time is linear, and the queue never holds more than the widest level.
A DFS that carries the depth and appends into levels[depth] also works, since a preorder walk meets each level's nodes left to right.
Complexity
- Time:
O(n) - Space:
O(w), w = maximum width of the tree (O(n) worst case)
Python
class Solution:
def levelOrder(self, root: Optional[TreeNode]) -> List[List[int]]:
if root is None:
return []
levels = []
queue = deque([root])
while queue:
level = []
for _ in range(len(queue)): # exactly the nodes of this level
node = queue.popleft()
level.append(node.val)
if node.left:
queue.append(node.left)
if node.right:
queue.append(node.right)
levels.append(level)
return levels
JavaScript
var levelOrder = function(root) {
if (root === null) return [];
const levels = [];
let queue = [root];
while (queue.length > 0) {
const level = [];
const next = [];
for (const node of queue) {
level.push(node.val);
if (node.left) next.push(node.left);
if (node.right) next.push(node.right);
}
levels.push(level);
queue = next; // the children form the next level
}
return levels;
};
What the interviewer is checking
It checks that you know BFS cold and can separate levels cleanly, which is the template for many follow-ups (right side view, zigzag order, level averages).
Mistakes to avoid
- Using
len(queue)inside the loop condition while also pushing children, which mixes two levels together. - Forgetting the empty tree and returning
[[]]instead of[]. - Popping from the front of a Python list (
pop(0)), which is O(n); usecollections.deque.
Follow-ups to expect
- Return the levels bottom-up instead? (Reverse the result at the end.)
- Alternate left-to-right and right-to-left per level? (Reverse every other level.)
- Return only the rightmost value per level? (Last node of each round.)
In real software
Org-chart and file-system browsers show items by depth, and web crawlers and social-network "degrees of separation" features process nodes level by level with the same queue technique.