Binary Tree Zigzag Level Order Traversal
You are given the root of a binary tree. Group its values by depth and return one list per level, from the root level down to the deepest level.
The reading direction alternates from level to level: read the root level left to right, the next level right to left, the one after that left to right again, and so on. If the tree is empty, return an empty list.
The tree is given as a level-order array in which null marks a missing child, so [1,2,3,null,4] is a root 1 with children 2 and 3, where 2 has only a right child 4.
Example 1
Example 2
Example 3
Constraints
- The number of nodes is between 0 and 2000.
-100 <= Node.val <= 100
Pattern Path · Trees: BFS · problem 95 of 169
Start simple
Run a separate depth-first search for every depth d to collect that level's nodes: O(n·h) time, which is O(n²) for a skewed tree.
The key idea
This is an ordinary level-order traversal with a twist that only affects how each level is written down, not how the tree is visited.
Use a queue. At the start of each round the queue holds exactly the nodes of one level, so record its size k, pop k nodes, collect their values in left-to-right order, and push their children (left first, then right) for the next round.
Keep a flag that flips after every level. When the flag says "right to left", reverse the collected values before appending them. Reversing a level of size k costs O(k), and every node belongs to exactly one level, so the total extra work is O(n).
Do not try to change the order in which children are pushed: that changes which nodes are visited next and quickly scrambles deeper levels. Keeping the visit order fixed and only reversing the output is what keeps the logic simple and correct.
Complexity
- Time:
O(n) - Space:
O(n)
Python
from collections import deque
class Solution:
def zigzagLevelOrder(self, root):
if root is None:
return []
result = []
queue = deque([root])
left_to_right = True
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)
if not left_to_right:
level.reverse()
result.append(level)
left_to_right = not left_to_right
return result
JavaScript
var zigzagLevelOrder = function(root) {
if (root === null) return [];
const result = [];
let level = [root];
let leftToRight = true;
while (level.length > 0) {
const values = level.map(node => node.val);
if (!leftToRight) values.reverse();
result.push(values);
const next = [];
for (const node of level) {
if (node.left) next.push(node.left);
if (node.right) next.push(node.right);
}
level = next;
leftToRight = !leftToRight;
}
return result;
};
What the interviewer is checking
It checks that you can run a level-by-level BFS cleanly and adapt it to a small twist without breaking the traversal itself.
Mistakes to avoid
- Swapping the order children are enqueued on alternate levels, which corrupts the order of later levels.
- Forgetting to handle an empty tree (root is null).
- Not fixing the level size before the inner loop, so nodes from the next level get mixed into the current one.
- Starting with the wrong direction: the root level is read left to right.
Follow-ups to expect
- Can you avoid the reversal? (Fill each level from the front or back.)
- Can you do it with depth-first search? (Pass depth, append to level list.)
- Can you use two stacks instead of a queue? (Alternate stacks, alternate child order.)
In real software
Level-by-level traversal shows up in rendering org charts and file trees by depth, and in breadth-first crawlers that process one hop distance at a time.