💡 The algorithm builds the result list level by level as recursion deepens.
traverse
Recurse into left child of 15 (null) at level 3
We recursively call dfs on node 15's left child, which is null, at level 3. The recursion returns immediately.
💡 Null children end recursion branches safely.
Line:if not node:
return
💡 Leaf nodes have no children, so recursion backtracks here.
traverse
Recurse into right child of 15 (null) at level 3
We recursively call dfs on node 15's right child, which is null, at level 3. The recursion returns immediately.
💡 Both children of leaf nodes are null, ending recursion branches.
Line:if not node:
return
💡 Recursion backtracks after visiting all children of a leaf node.
traverse
Return from node 15 and recurse into right child (7) of node 20 at level 2
After finishing node 15, recursion returns to node 20 and calls dfs on its right child (7) at level 2.
💡 Recursion explores all children of a node before returning.
Line:dfs(node.right, level + 1)
💡 The algorithm visits all nodes at a level before backtracking.
fill_row
Append value 7 to existing level 2 list
Since level 2 already exists in result, we append node 7's value to the existing list for level 2.
💡 Nodes at the same level are collected together in order of visitation.
Line:result[level].append(node.val)
💡 The algorithm maintains order of nodes within each level.
traverse
Recurse into left child of 7 (null) at level 3
We recursively call dfs on node 7's left child, which is null, at level 3. The recursion returns immediately.
💡 Null children end recursion branches safely.
Line:if not node:
return
💡 Leaf nodes have no children, so recursion backtracks here.
traverse
Recurse into right child of 7 (null) at level 3
We recursively call dfs on node 7's right child, which is null, at level 3. The recursion returns immediately.
💡 Both children of leaf nodes are null, ending recursion branches.
Line:if not node:
return
💡 Recursion backtracks after visiting all children of a leaf node.
return
Return from node 20 and then from root node 3
Having visited all children of node 20, recursion returns to root node 3, then finally returns from root after completing traversal.
💡 Recursion unwinds after all nodes are visited, returning the final result.
Line:return result
💡 The entire tree has been traversed and the result list is complete.
from typing import List, Optional
class TreeNode:
def __init__(self, val=0, left=None, right=None):
self.val = val
self.left = left
self.right = right
def dfs_level_order(root: Optional[TreeNode]) -> List[List[int]]:
result = [] # STEP 1: Initialize result list
def dfs(node: Optional[TreeNode], level: int):
if not node: # STEP 5,6,11,12,15,16: Return on null node
return
if level == len(result): # STEP 2,4,10: Add new list for new level
result.append([])
result[level].append(node.val) # STEP 2,4,8,10,14: Append node value to level list
dfs(node.left, level + 1) # STEP 3,5,9,11,15: Recurse left child
dfs(node.right, level + 1) # STEP 7,6,12,13,16: Recurse right child
dfs(root, 0) # STEP 1: Start DFS at root
return result # STEP 17: Return final result
# Example usage:
# root = TreeNode(3, TreeNode(9), TreeNode(20, TreeNode(15), TreeNode(7)))
# print(dfs_level_order(root))
📊
Binary Tree Level Order Traversal - Watch the Algorithm Execute, Step by Step
Watching the recursion and level tracking live reveals how the algorithm builds the level order result without explicit queues, making the process intuitive.
Seeing recursion return on null nodes helps understand how leaf nodes terminate recursion branches.
Practice
(1/5)
1. Consider the following code snippet implementing the optimal approach to find the maximum width of a binary tree. Given the tree below:
1
/ \
3 2
/ \
5 9
What is the value of max_width returned by the function?
easy
A. 3
B. 2
C. 4
D. 5
Solution
Step 1: Trace first level
Root node 1 at index 0; max_width updated to 1.
Step 2: Trace second level
Nodes 3 and 2 at indices 0 and 1 (after normalization). Width = 1 - 0 + 1 = 2.
Step 3: Trace third level
Nodes 5 and 9 at indices 0 and 3 (after normalization). Width = 3 - 0 + 1 = 4.
Final Answer:
Option C -> Option C
Quick Check:
Maximum width is 4 at the last level [OK]
Hint: Normalize indices per level to compute width correctly [OK]
Common Mistakes:
Not normalizing indices before computing width
Counting nodes instead of width including null gaps
Off-by-one error in width calculation
2. You are given a binary tree where each node may have zero, one, or two children. Your task is to connect each node's next pointer to its next right node on the same level. If there is no next right node, the next pointer should be set to NULL. Which approach guarantees an optimal solution with O(n) time and O(h) space, where h is the tree height?
easy
A. Use a dynamic programming approach to store connections and build them bottom-up.
B. Perform a level order traversal using a queue to connect nodes level by level.
C. Use a recursive top-down approach that leverages already established next pointers to connect nodes without extra queue space.
D. Apply a greedy approach that connects nodes as soon as they are discovered during DFS.
Solution
Step 1: Understand the problem constraints
The problem requires connecting next pointers in any binary tree, not necessarily perfect or complete, with O(n) time and O(h) space.
Step 2: Evaluate approaches
Using a queue (Perform a level order traversal using a queue to connect nodes level by level.) uses O(n) space, violating the space constraint. DP (Use a dynamic programming approach to store connections and build them bottom-up.) is not applicable here. Greedy DFS (Apply a greedy approach that connects nodes as soon as they are discovered during DFS.) fails to guarantee correct connections across siblings at the same level. The recursive top-down approach (Use a recursive top-down approach that leverages already established next pointers to connect nodes without extra queue space.) uses existing next pointers to traverse levels efficiently with O(h) recursion stack space.
Final Answer:
Option C -> Option C
Quick Check:
Top-down recursion with next pointers -> O(n) time, O(h) space [OK]
Hint: Top-down recursion uses next pointers to avoid extra space [OK]
Common Mistakes:
Assuming BFS with queue is optimal space-wise
Trying DP bottom-up which doesn't fit this problem
Using DFS greedily without next pointers
3. You are given a binary tree and need to determine if it is symmetric around its center. Which approach best guarantees an optimal solution by comparing nodes in pairs using a queue and terminating early when asymmetry is detected?
easy
A. Recursive depth-first traversal comparing left subtree to left subtree
B. Dynamic programming storing subtree symmetry states bottom-up
C. Greedy traversal checking only the root and immediate children
D. Iterative breadth-first search using a queue to compare mirrored node pairs with early termination
Solution
Step 1: Understand the problem requirement
The problem requires checking if a tree is symmetric, which means the left subtree is a mirror reflection of the right subtree.
Step 2: Identify the approach that compares mirrored nodes efficiently
Using an iterative BFS with a queue to compare pairs of nodes from left and right subtrees simultaneously allows early detection of asymmetry and avoids unnecessary traversal.
Final Answer:
Option D -> Option D
Quick Check:
Iterative BFS with paired nodes and early termination is optimal for symmetry check [OK]
Comparing left subtree to left subtree instead of mirrored right subtree
Using greedy checks that miss deeper asymmetry
Assuming symmetry can be checked by root and immediate children only
4. Suppose the binary tree can have nodes with duplicate values and you want to return the right side view but also include all nodes visible from the right side at each depth (not just the first). Which modification to the optimal DFS approach correctly handles this variant?
hard
A. Use DFS with right-first traversal but overwrite the node value at each depth to keep the last visited node.
B. Use BFS level order traversal and collect the last node at each level only.
C. Change DFS to visit left child first and append all nodes at each depth to a list.
D. Modify DFS to visit right child first and append every node encountered at each depth to a list instead of only the first.
Solution
Step 1: Understand requirement
We want all nodes visible from the right side at each depth, not just the first.
Step 2: Modify DFS to collect all nodes per depth
Visiting right child first ensures rightmost nodes are visited first, but we must append every node at that depth to a list, not just the first.
Step 3: Why other options fail
Left-first traversal or overwriting values loses rightmost visibility; BFS collecting only last node misses duplicates.
Final Answer:
Option D -> Option D
Quick Check:
Right-first DFS appending all nodes per depth captures all visible nodes [OK]
Hint: Right-first DFS appending all nodes per depth [OK]
Common Mistakes:
Using left-first traversal loses rightmost nodes
Appending only first or last node per depth misses duplicates
Overwriting values loses multiple visible nodes
5. Suppose the problem is extended so that the tree nodes can have multiple children (not just binary), and you need to check if the tree is symmetric around its center. Which modification to the BFS approach is necessary to correctly handle this case?
hard
A. Enqueue children in normal order and compare corresponding children pairs directly
B. Enqueue children in mirrored order and compare pairs from opposite ends of the children list
C. Use a recursive approach only, as BFS cannot handle multiple children
D. Check symmetry only at the root level and ignore deeper levels
Solution
Step 1: Understand symmetry in multi-child trees
Symmetry means the first child on the left subtree mirrors the last child on the right subtree, second mirrors second last, etc.
Step 2: Modify BFS to enqueue children in mirrored order
Enqueue children pairs from opposite ends of the children list to compare mirrored positions correctly.
Final Answer:
Option B -> Option B
Quick Check:
Mirrored enqueue order for multiple children preserves symmetry checks [OK]