Binary Tree Zigzag Level Order Traversal (LeetCode 103)
You're given the root of a binary tree. Traverse it level by level, but alternate the reading direction each level — left-to-right on one level, then right-to-left on the next, and so on. Return the node values collected this way, one inner list per level.
Worked Examples
root = [3,9,20,null,null,15,7][[3],[20,9],[15,7]][3], depth 1 is read right to left as [20,9], and depth 2 left to right as [15,7].root = [1][[1]]root = [][]⚖️Formal Constraints & Bounds
The number of nodes in the tree is in the range
[0, 2000].-100 <= Node.val <= 100
Core Insight
Decoupling FIFO child queue traversal from level-buffer insertion direction avoids complex queue reordering.
Real-World Scenario & Production Applications
Printing hierarchical snake-like raster patterns, bidirectional visual tree rendering.
Step-by-Step Execution Trace Table
Step-by-Step Wavefront Progression
- Step 1 (Root Seed, Ring 0, d=0):
queue = [3]. Seed queue with root node3. Set direction flagleft_to_right = True. Initialoutput = []. - Step 2 (Snapshot Ring 0, level_size=1, d=0):
level_size = 1. Freeze Ring 0 boundary. Direction: Left Right. - Step 3 (Dequeue 3 & Enqueue Children, Ring 0, d=0): Pop
3append to current level:[3]. Enqueue left child9and right child20queue = [9, 20]. Commit Ring 0output = [[3]]. Toggleleft_to_right = False📸. - Step 4 (Snapshot Ring 1, level_size=2, d=1):
level_size = 2. Freeze Ring 1 boundary. Direction: Right Left.queue = [9, 20]. - Step 5 (Dequeue 9, Reverse Level Append, Ring 1, d=1): Pop
9appendleft to level buffer:current_level = [9]. Node 9 has no children. Remaining in Ring 1: 1 node. - Step 6 (Dequeue 20 & Enqueue Children, Ring 1, d=1): Pop
20appendleft:current_level = [20, 9]. Enqueue left child15and right child7queue = [15, 7]. Commit Ring 1output = [[3], [20, 9]]. Toggleleft_to_right = True📸. - Step 7 (Snapshot Ring 2, level_size=2, d=2):
level_size = 2. Freeze Ring 2 boundary. Direction: Left Right.queue = [15, 7]. - Step 8 (Dequeue 15, Normal Append, Ring 2, d=2): Pop
15append:current_level = [15]. Node 15 has no children. Remaining in Ring 2: 1 node. - Step 9 (Dequeue 7, Normal Append, Ring 2, d=2): Pop
7append:current_level = [15, 7]. Node 7 has no children. Commit Ring 2output = [[3], [20, 9], [15, 7]]📸. - Step 10 (Queue Empty, Complete, d=2):
queue = []. Zigzag level traversal complete. Search Complete: return[[3], [20, 9], [15, 7]]✅.
root = [3,9,20,null,null,15,7]Expected:[[3],[20,9],[15,7]]| 1 | queue = deque([root]) |
| 2 | levels = [] |
| 3 | left_to_right = True |
| 4 | while queue: |
| 5 | level = deque() |
| 6 | for _ in range(len(queue)): |
| 7 | node = queue.popleft() |
| 8 | if left_to_right: |
| 9 | level.append(node.val) |
| 10 | else: |
| 11 | level.appendleft(node.val) |
| 12 | append the children of node to queue |
| 13 | levels.append(list(level)) |
| 14 | left_to_right = not left_to_right |
| 15 | return levels |
Conceptual Narrative
🧭 Conceptual Foundation & Pattern Intuition
Zigzag Level Order Traversal alternates node value collection left-to-right on even levels () and right-to-left on odd levels (). The critical architectural mistake many engineers make is attempting to alter the BFS queue's physical insertion order (pushing right children before left children), which scrambles the FIFO generational structure and destroys the tree's geometry. The solution decouples traversal from formatting: allow the standard FIFO BFS queue to discover nodes strictly left-to-right on every level, but collect the level's values into a double-ended queue (deque) that appends to the right or left based on depth parity.
🏟️ The Analogy: The Farmer Plowing a Terraced Orchard
Imagine a farmer plowing an orchard planted on a hillside with horizontal terraces. On terrace 0, the farmer walks tractor from West to East. At the end of the row, instead of driving all the way back to the West side to start row 1, the farmer drops down to terrace 1 and drives from East to West. On terrace 2, the farmer turns and drives West to East again. The trees on the hillside don't move; only the direction the farmer records the harvest changes with each terrace.
🔑 Why It Works
Notice that the core BFS queue logic is 100% identical to LC 102. By using level_vals.appendleft() on alternating levels, we achieve execution time with zero array reversal overhead.
level reversal overhead: Calling
level_vals.reverse()on every alternate level creates unnecessary array copies. Using a double-ended queue (deque.appendleft) preserves directional insertion.Direction flag flipped inside inner loop: Inverting the
is_left_to_rightboolean inside thefor _ in range(level_size):loop instead of once per level after the inner loop completes.Altering queue traversal order: Attempting to alternate the FIFO order of the BFS exploration queue itself instead of keeping queue FIFO and altering only the emitted level buffer insertion direction.
4-Phase Thought Process Model
Pattern Recognition Signals
The 10-second spot
Level-by-level tree traversal with alternating left/right output order.
Formulating the Predicate & Invariants
Turning intuition into a boolean rule
Invariant: BFS queue maintains strict FIFO level order while level buffer handles directional formatting.
Silent Failure Traps & Edge Cases
Where confident candidates still lose points
Reversing arrays at each level with
list.reverse():O(N)extra copying per level; use adequewithappendleftforO(1)insertions.
The 60-Second Interview Pitch
Say this out loud before you type a single line
"I perform standard level-order BFS using a queue. For each level, I initialize a deque buffer. If left-to-right, I append to the tail; otherwise I appendleft to the head. I toggle the boolean flag after each level. Runs in
O(N)time andO(N)space."
Complexity & Mathematical Proof
O(N)
Look at the execution steps: Processes tree level-by-level; reverses or appends to deque based on boolean flag in O(1) per node. Total N nodes.
O(W) Auxiliary
Look at memory allocations: Call stack uses O(1) Iterative. Queue holds max level width W nodes.
T(N) = O(N)
Derivation Progression
O(K) nodes per level K
Dequeues all nodes in current tier.
O(1) append/appendleft
Builds current level list in alternating order.
O(N) total time
Every node visited once.
Variable Definitions
Total number of nodes in the binary tree
Maximum level width (at most ⌈N/2⌉ nodes)
Memory Architecture & Bounds
O(1) Iterative
O(W) Queue holding max level width W
O(N) 2D zigzag result
Boundary Best / Worst Cases
Graph & Tree Traversal Frontier
Senior SWE Deconstruction & Hardware Caveats
Triggers: "zigzag level order traversal", "alternate between left-to-right and right-to-left". Level order traversal with alternating directional orientation. A Senior SWE avoids complex double-ended queue insertion games: retain the standard left-to-right FIFO queue for tree traversal, and simply reverse the level output list when the alternating flag is set!
. Time budget is linear time.
Altering child enqueue order based on the zigzag flag: enqueuing right-then-left on even levels corrupts the geometric order of children for all subsequent tiers.
Binary Tree Zigzag Level Order Traversal (LeetCode 103)
You're given the root of a binary tree. Traverse it level by level, but alternate the reading direction each level — left-to-right on one level, then right-to-left on the next, and so on. Return the node values collected this way, one inner list per level.
Worked Examples
root = [3,9,20,null,null,15,7][[3],[20,9],[15,7]][3], depth 1 is read right to left as [20,9], and depth 2 left to right as [15,7].root = [1][[1]]root = [][]⚖️Formal Constraints & Bounds
The number of nodes in the tree is in the range
[0, 2000].-100 <= Node.val <= 100
Core Insight
Decoupling FIFO child queue traversal from level-buffer insertion direction avoids complex queue reordering.
Real-World Scenario & Production Applications
Printing hierarchical snake-like raster patterns, bidirectional visual tree rendering.
Step-by-Step Execution Trace Table
Step-by-Step Wavefront Progression
- Step 1 (Root Seed, Ring 0, d=0):
queue = [3]. Seed queue with root node3. Set direction flagleft_to_right = True. Initialoutput = []. - Step 2 (Snapshot Ring 0, level_size=1, d=0):
level_size = 1. Freeze Ring 0 boundary. Direction: Left Right. - Step 3 (Dequeue 3 & Enqueue Children, Ring 0, d=0): Pop
3append to current level:[3]. Enqueue left child9and right child20queue = [9, 20]. Commit Ring 0output = [[3]]. Toggleleft_to_right = False📸. - Step 4 (Snapshot Ring 1, level_size=2, d=1):
level_size = 2. Freeze Ring 1 boundary. Direction: Right Left.queue = [9, 20]. - Step 5 (Dequeue 9, Reverse Level Append, Ring 1, d=1): Pop
9appendleft to level buffer:current_level = [9]. Node 9 has no children. Remaining in Ring 1: 1 node. - Step 6 (Dequeue 20 & Enqueue Children, Ring 1, d=1): Pop
20appendleft:current_level = [20, 9]. Enqueue left child15and right child7queue = [15, 7]. Commit Ring 1output = [[3], [20, 9]]. Toggleleft_to_right = True📸. - Step 7 (Snapshot Ring 2, level_size=2, d=2):
level_size = 2. Freeze Ring 2 boundary. Direction: Left Right.queue = [15, 7]. - Step 8 (Dequeue 15, Normal Append, Ring 2, d=2): Pop
15append:current_level = [15]. Node 15 has no children. Remaining in Ring 2: 1 node. - Step 9 (Dequeue 7, Normal Append, Ring 2, d=2): Pop
7append:current_level = [15, 7]. Node 7 has no children. Commit Ring 2output = [[3], [20, 9], [15, 7]]📸. - Step 10 (Queue Empty, Complete, d=2):
queue = []. Zigzag level traversal complete. Search Complete: return[[3], [20, 9], [15, 7]]✅.
root = [3,9,20,null,null,15,7]Expected:[[3],[20,9],[15,7]]| 1 | queue = deque([root]) |
| 2 | levels = [] |
| 3 | left_to_right = True |
| 4 | while queue: |
| 5 | level = deque() |
| 6 | for _ in range(len(queue)): |
| 7 | node = queue.popleft() |
| 8 | if left_to_right: |
| 9 | level.append(node.val) |
| 10 | else: |
| 11 | level.appendleft(node.val) |
| 12 | append the children of node to queue |
| 13 | levels.append(list(level)) |
| 14 | left_to_right = not left_to_right |
| 15 | return levels |
Conceptual Narrative
🧭 Conceptual Foundation & Pattern Intuition
Zigzag Level Order Traversal alternates node value collection left-to-right on even levels () and right-to-left on odd levels (). The critical architectural mistake many engineers make is attempting to alter the BFS queue's physical insertion order (pushing right children before left children), which scrambles the FIFO generational structure and destroys the tree's geometry. The solution decouples traversal from formatting: allow the standard FIFO BFS queue to discover nodes strictly left-to-right on every level, but collect the level's values into a double-ended queue (deque) that appends to the right or left based on depth parity.
🏟️ The Analogy: The Farmer Plowing a Terraced Orchard
Imagine a farmer plowing an orchard planted on a hillside with horizontal terraces. On terrace 0, the farmer walks tractor from West to East. At the end of the row, instead of driving all the way back to the West side to start row 1, the farmer drops down to terrace 1 and drives from East to West. On terrace 2, the farmer turns and drives West to East again. The trees on the hillside don't move; only the direction the farmer records the harvest changes with each terrace.
🔑 Why It Works
Notice that the core BFS queue logic is 100% identical to LC 102. By using level_vals.appendleft() on alternating levels, we achieve execution time with zero array reversal overhead.
level reversal overhead: Calling
level_vals.reverse()on every alternate level creates unnecessary array copies. Using a double-ended queue (deque.appendleft) preserves directional insertion.Direction flag flipped inside inner loop: Inverting the
is_left_to_rightboolean inside thefor _ in range(level_size):loop instead of once per level after the inner loop completes.Altering queue traversal order: Attempting to alternate the FIFO order of the BFS exploration queue itself instead of keeping queue FIFO and altering only the emitted level buffer insertion direction.
4-Phase Thought Process Model
Pattern Recognition Signals
The 10-second spot
Level-by-level tree traversal with alternating left/right output order.
Formulating the Predicate & Invariants
Turning intuition into a boolean rule
Invariant: BFS queue maintains strict FIFO level order while level buffer handles directional formatting.
Silent Failure Traps & Edge Cases
Where confident candidates still lose points
Reversing arrays at each level with
list.reverse():O(N)extra copying per level; use adequewithappendleftforO(1)insertions.
The 60-Second Interview Pitch
Say this out loud before you type a single line
"I perform standard level-order BFS using a queue. For each level, I initialize a deque buffer. If left-to-right, I append to the tail; otherwise I appendleft to the head. I toggle the boolean flag after each level. Runs in
O(N)time andO(N)space."
Complexity & Mathematical Proof
O(N)
Look at the execution steps: Processes tree level-by-level; reverses or appends to deque based on boolean flag in O(1) per node. Total N nodes.
O(W) Auxiliary
Look at memory allocations: Call stack uses O(1) Iterative. Queue holds max level width W nodes.
T(N) = O(N)
Derivation Progression
O(K) nodes per level K
Dequeues all nodes in current tier.
O(1) append/appendleft
Builds current level list in alternating order.
O(N) total time
Every node visited once.
Variable Definitions
Total number of nodes in the binary tree
Maximum level width (at most ⌈N/2⌉ nodes)
Memory Architecture & Bounds
O(1) Iterative
O(W) Queue holding max level width W
O(N) 2D zigzag result
Boundary Best / Worst Cases
Graph & Tree Traversal Frontier
Senior SWE Deconstruction & Hardware Caveats
Triggers: "zigzag level order traversal", "alternate between left-to-right and right-to-left". Level order traversal with alternating directional orientation. A Senior SWE avoids complex double-ended queue insertion games: retain the standard left-to-right FIFO queue for tree traversal, and simply reverse the level output list when the alternating flag is set!
. Time budget is linear time.
Altering child enqueue order based on the zigzag flag: enqueuing right-then-left on even levels corrupts the geometric order of children for all subsequent tiers.