Bird
Raised Fist0
Interview Preptree-dfseasyAmazonMicrosoftFacebook

Path Sum

Choose your preparation mode4 modes available

Start learning this pattern below

Jump into concepts and practice - no test required

or
Recommended
Test this pattern10 questions across easy, medium, and hard to know if this pattern is strong
Steps
setup

Start DFS at root node 5 with current sum 0

The algorithm begins by calling dfs on the root node (value 5) with an initial current sum of 0.

💡 This initializes the recursion and sets the starting point for accumulating sums along paths.
Line:return dfs(root, 0)
💡 The root node is the entry point for the DFS traversal.
📊
Path Sum - Watch the Algorithm Execute, Step by Step
Watching the algorithm step through each node and decision reveals how early stopping works and how the recursion stack evolves, making the path sum logic crystal clear.
Step 1/11
·Active fillAnswer cell
Current node: 1
54811721341
DFS Stack
1 (entered)curr_sum=0
Current node: 1
54811721341
DFS Stack
1 (entered)curr_sum=5
Current node: 2
54811721341
DFS Stack
2 (entered)curr_sum=51 (left_done)curr_sum=5
Current node: 2
54811721341
DFS Stack
2 (entered)curr_sum=91 (left_done)curr_sum=5
Current node: 4
54811721341
DFS Stack
4 (entered)curr_sum=92 (left_done)curr_sum=91 (left_done)curr_sum=5
Current node: 4
54811721341
DFS Stack
4 (entered)curr_sum=202 (left_done)curr_sum=91 (left_done)curr_sum=5
Current node: 5
54811721341
DFS Stack
5 (entered)curr_sum=204 (left_done)curr_sum=202 (left_done)curr_sum=91 (left_done)curr_sum=5
Current node: 5
54811721341
DFS Stack
5 (returning)curr_sum=274 (left_done)curr_sum=202 (left_done)curr_sum=91 (left_done)curr_sum=5
Return: false
Current node: 6
54811721341
DFS Stack
6 (entered)curr_sum=204 (right_done)curr_sum=202 (left_done)curr_sum=91 (left_done)curr_sum=5
Current node: 6
54811721341
DFS Stack
6 (returning)curr_sum=224 (returning)curr_sum=222 (left_done)curr_sum=91 (left_done)curr_sum=5
Return: true
Current node: 1
54811721341
Return: true

Key Takeaways

DFS explores each root-to-leaf path accumulating sums to check for target sum.

This insight is hard to see from code alone because recursion hides the path exploration order.

Early stopping returns true immediately when a valid path is found, avoiding unnecessary work.

Visualizing the call stack and return values clarifies how early stopping improves efficiency.

Backtracking occurs when a path fails, and the algorithm explores alternative branches systematically.

Seeing the recursion unwind and try other branches concretely shows how all paths are checked.

Practice

(1/5)
1. Consider the following Python code implementing the Morris Preorder Traversal approach to sum root-to-leaf numbers. Given the binary tree: 1 / \ 2 3 What is the final value of the variable total returned by sumNumbers?
easy
A. 5
B. 15
C. 25
D. 26

Solution

  1. Step 1: Trace path 1->2

    current_number accumulates 1 then 12; leaf node 2 adds 12 to total.
  2. Step 2: Trace path 1->3

    current_number resets to 1, then accumulates 13; leaf node 3 adds 13 to total. Total = 12 + 13 = 25.
  3. Step 3: Check for off-by-one or missed increments

    Integer division after visiting left subtree correctly adjusts current_number; no extra addition occurs.
  4. Final Answer:

    Option C -> Option C
  5. Quick Check:

    Sum of 12 and 13 is 25, matching code behavior [OK]
Hint: Trace current_number updates carefully at each node [OK]
Common Mistakes:
  • Off-by-one in current_number division
  • Adding non-leaf nodes to total
2. What is the time complexity of the optimal DFS with two-value return solution for the House Robber III problem on a tree with n nodes?
medium
A. O(n^2) due to checking grandchildren nodes explicitly
B. O(n) but with extra O(n) space for memoization arrays
C. O(n) because each node is visited once in DFS
D. O(n log n) because of recursive calls and combining results

Solution

  1. Step 1: Identify DFS traversal cost

    The algorithm visits each node exactly once in a postorder DFS traversal.
  2. Step 2: Analyze operations per node

    At each node, constant time operations are done: combining left and right child results, no repeated work.
  3. Final Answer:

    Option C -> Option C
  4. Quick Check:

    Linear traversal of n nodes -> O(n) time [OK]
Hint: DFS visits each node once, no repeated subproblems [OK]
Common Mistakes:
  • Assuming O(n^2) due to grandchildren checks
  • Confusing recursion stack space with time complexity
3. The following code attempts to find the Lowest Common Ancestor using parent pointers. Identify the line containing the subtle bug that causes incorrect results when one node is ancestor of the other.
def lowestCommonAncestor(root, p, q):
    parent = {root: None}
    stack = [root]
    while p not in parent or q not in parent:
        node = stack.pop()
        if node.left:
            parent[node.left] = node
            stack.append(node.left)
        if node.right:
            parent[node.right] = node
            stack.append(node.right)

    ancestors = set()
    while p:
        ancestors.add(p)
        p = parent[p]
    while q not in ancestors:
        q = parent[q]
    return q
medium
A. Line: while p not in parent or q not in parent:
B. Line: while p:
C. Line: while q not in ancestors:
D. Line: parent = {root: None}

Solution

  1. Step 1: Analyze parent map construction loop

    The loop 'while p not in parent or q not in parent:' ensures both nodes are in the parent map before ancestor sets are built.
  2. Step 2: Identify subtle bug

    If one node is ancestor of the other, the loop may terminate prematurely if only one node is in parent map, causing KeyError later.
  3. Step 3: Explanation

    The bug is that the loop condition does not guarantee both nodes are fully processed in the parent map before ancestor traversal.
  4. Final Answer:

    Option A -> Option A
  5. Quick Check:

    Loop condition must ensure both nodes are in parent map to avoid errors [OK]
Hint: Parent map construction loop must fully process both nodes [OK]
Common Mistakes:
  • Assuming parent map always complete
  • Ignoring incomplete parent map causing KeyError
  • Misplacing bug in ancestor set loops
4. What is the time complexity of the BFS-based serialization and deserialization of a binary tree with n nodes, assuming the tree is balanced? Consider both serialization and deserialization separately.
medium
A. Serialization: O(n log n), Deserialization: O(n log n)
B. Serialization: O(n), Deserialization: O(n^2)
C. Serialization: O(n), Deserialization: O(n)
D. Serialization: O(n^2), Deserialization: O(n)

Solution

  1. Step 1: Analyze serialization time

    Each node is enqueued and dequeued exactly once, so serialization is O(n).
  2. Step 2: Analyze deserialization time

    Deserialization processes each node once, reconstructing the tree in O(n) time.
  3. Final Answer:

    Option C -> Option C
  4. Quick Check:

    Both serialization and deserialization scale linearly with number of nodes [OK]
Hint: Each node is processed once in BFS serialization/deserialization [OK]
Common Mistakes:
  • Assuming deserialization is O(n^2) due to nested loops
  • Confusing tree height with number of nodes
  • Thinking serialization is O(n log n) due to queue operations
5. Consider the following buggy deserialization code snippet for BFS-based tree reconstruction. Which line contains the subtle bug that causes incorrect tree structure when deserializing?
def deserialize(data):
    if not data:
        return None
    vals = data.split(',')
    root = TreeNode(int(vals[0]))
    queue = deque([root])
    i = 1
    while queue:
        node = queue.popleft()
        if vals[i] != 'X':
            node.left = TreeNode(int(vals[i]))
            queue.append(node.left)
        i += 1
        if vals[i] != 'X':
            node.right = TreeNode(int(vals[i]))
            queue.append(node.right)
        i += 1
    return root
medium
A. Line: if vals[i] != 'X': (left child check)
B. Line: i += 1 (after left child assignment)
C. Line: if vals[i] != 'X': (right child check)
D. Line: while queue: (loop condition)

Solution

  1. Step 1: Identify potential infinite loop

    The loop condition 'while queue:' does not check if 'i' has exceeded vals length, risking index out of range or infinite loop.
  2. Step 2: Understand impact on deserialization

    Without checking 'i < len(vals)', the loop may continue after all nodes processed, causing errors or incorrect tree structure.
  3. Final Answer:

    Option D -> Option D
  4. Quick Check:

    Loop condition must ensure 'i' stays within bounds to avoid deserialization bugs [OK]
Hint: Loop must check index bounds to avoid infinite loops [OK]
Common Mistakes:
  • Not checking index bounds in deserialization loops
  • Mixing up left and right child assignments
  • Forgetting to append children to queue