Queue ArrayDeque · poll() at the front (left), add() at the back · yellow = the level being read
res one list per level
public List<List<Integer>> levelOrder(TreeNode root) { List<List<Integer>> res = new ArrayList<>(); Queue<TreeNode> q = new ArrayDeque<>(); if (root != null) { q.add(root); } while (!q.isEmpty()) { List<Integer> level = new ArrayList<>(); int size = q.size(); for (int i = 0; i < size; i++) { // this level only TreeNode node = q.poll(); level.add(node.val); if (node.left != null) { q.add(node.left); } if (node.right != null) { q.add(node.right); } } res.add(level); } return res;}
- level #
- —
- size
- —
- node
- —
- level
- —
- q
- []
Why it works
- A queue visits nodes in order of distance from the root: first in, first out, so every node of level d leaves before any node of level d + 1.
- Freeze
size = q.size()at the start of each level. At that moment the queue holds exactly one level. The children appended during the loop wait for the next pass, so the levels never mix. - Pitfall: writing
i < q.size()as the loop condition. The size grows as children are added, so the levels mix; read it once intosize. Also avoid anArrayListwithremove(0)as the queue: O(n) per pop, whileArrayDeque.poll()is O(1). - Cost: each node is appended and popped once, O(n) time. The queue holds at most one level plus part of the next: O(w), up to about n/2 for a full tree.
- DFS alternative: recurse with the depth and add to
res.get(depth). Same output, O(h) stack. The level loop is reused by Right Side View (LeetCode 199), Zigzag Order (103) and Maximum Depth (104).