Binary Tree Level Order Traversal
Return node values level by level, each level its own list.
Open on LeetCode ↗Intuition
A queue processes nodes in arrival order, and children arrive after parents — so the queue naturally holds one level's tail and the next level's head. Snapshot the queue length at each round: exactly that many pops belong to the current level.
The moment a tree problem mentions levels — level order, right side view, zigzag, minimum depth, largest value per row — you want BFS with a queue, not DFS. The one trick that makes it work is snapshotting len(q) before draining: that count is exactly the current level's width, because everything added during the drain belongs to the next level.
Approach
BFS with a queue
Start with the root. Pop a node, record it, push its children — classic breadth-first.
Level boundary = queue length
Before each round, size = len(queue) is the count of the current level. Pop exactly size nodes into one sublist.
Children queue for the next round
Everything pushed during a round is the next level, processed in the next iteration.
Solution & live demo
Common pitfalls
Reading the queue length inside the loop
while q:
level = []
for _ in range(len(q)):
node = q.popleft()
...while q:
level = []
size = len(q)
for _ in range(size):
...Python evaluates range(len(q)) once, so this specific form is safe — but it reads as though it re-checks, and translated literally into a while i < q.size() loop in another language it silently absorbs the next level's children into the current row. Capturing the size in a named variable makes the intent unambiguous.
Using a list and pop(0) as a queue
q = [root] node = q.pop(0)
q = deque([root]) node = q.popleft()
list.pop(0) shifts every remaining element left, so it's O(n) per call and turns the traversal into O(n²). deque.popleft() is O(1).
Not handling an empty tree
res, q = [], deque([root])
if not root: return [] res, q = [], deque([root])
A None root gets queued as a real entry, then node.val raises AttributeError. Guard before the queue is seeded.
Edge cases
No rounds → [].
Every level has one node → n singleton lists.