Skip to content

Instantly share code, notes, and snippets.

@ascherj
Created July 30, 2025 21:42
Show Gist options
  • Select an option

  • Save ascherj/e552d42059948b533bdf48a9abbbb8c9 to your computer and use it in GitHub Desktop.

Select an option

Save ascherj/e552d42059948b533bdf48a9abbbb8c9 to your computer and use it in GitHub Desktop.

πŸ§‘β€πŸ’» Interviewer Guide: Path Sum (UMPIRE Method)

https://leetcode.com/problems/path-sum/

πŸ“Œ Problem Statement

Given the root of a binary tree and an integer targetSum,
Return True if the tree has a root-to-leaf path such that the sum of the node values along the path equals targetSum.

A leaf is a node with no children.


🧭 U β€” Understand the Problem

Interviewer Prompts & Possible Answers:

  • "Can you restate the problem in your own words?"
    β†’ "Sure, we need to check if there's a path from the root node to any leaf where the sum of the node values equals the given target."

  • "What's the difference between any path and a root-to-leaf path?"
    β†’ "Any path could end at an internal node, but a root-to-leaf path must go all the way down to a node with no children."

  • "What qualifies a node as a leaf in this context?"
    β†’ "A node with no left or right children."

  • "What should the function return if the tree is empty?"
    β†’ "If the tree is empty, there's no path at all, so it should return False."

  • "Can node values be negative?"
    β†’ "Yes, node values can be negative, which means we can't use early termination optimizations."

  • "What if the tree has only one node?"
    β†’ "A single node is both root and leaf, so we just check if its value equals the target sum."


πŸ§ͺ M β€” Match with Patterns

Interviewer Prompts & Possible Answers:

  • "What kind of traversal do you think fits best here?"
    β†’ "Depth-first search makes sense since we're exploring complete paths from root to leaves."

  • "Have you seen problems involving root-to-leaf paths before?"
    β†’ "Yes, similar to problems like path sum collection, max depth, or binary tree path listing."

  • "Do you think recursion or iteration would work better for this?"
    β†’ "Recursion feels more natural because the structure of the problem mirrors the recursive tree traversal. Iteration would need a stack and extra bookkeeping."

  • "What's the key insight for solving this recursively?"
    β†’ "At each node, we reduce the problem by subtracting the current node's value from the target and recursing on children."


πŸ› οΈ P β€” Plan the Solution

Interviewer Prompts & Possible Answers:

  • "Can you walk me through how you'd approach this recursively?"
    β†’ "At each node, subtract the current node's value from the target. If we reach a leaf and the remaining sum is zero, we return true."

  • "What's your base case?"
    β†’ "If the node is None (empty tree), return False. If we're at a leaf node, check if the remaining sum equals the node's value."

  • "How do you reduce the problem as you move down the tree?"
    β†’ "We keep subtracting the node's value from the target and pass the new target down to the children."

  • "How would you handle the target sum at each step?"
    β†’ "I'd track the remaining sum as I recurse down, updating it by subtracting the current node's value."

  • "What happens when you have both left and right children?"
    β†’ "We need to check both subtrees. If either subtree has a valid path, we return True."

  • "Could you outline the algorithm step by step?"
    β†’ "1. Handle null tree case. 2. Check if current node is a leaf and equals remaining target. 3. Recursively check left and right subtrees with updated target. 4. Return true if either subtree has a valid path."


⌨️ I β€” Implement

Recursive Solution

class TreeNode:
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right

def hasPathSum(root: TreeNode, targetSum: int) -> bool:
    # Base case: empty tree
    if not root:
        return False
    
    # If we're at a leaf node, check if the current value equals targetSum
    if not root.left and not root.right:
        return root.val == targetSum
    
    # Recursively check left and right subtrees with updated sum
    remainingSum = targetSum - root.val
    return (
        hasPathSum(root.left, remainingSum) or 
        hasPathSum(root.right, remainingSum)
    )

Iterative Solution (Alternative)

def hasPathSum(root: TreeNode, targetSum: int) -> bool:
    if not root:
        return False
    
    # Stack stores tuples of (node, remaining_sum_needed)
    stack = [(root, targetSum - root.val)]
    
    while stack:
        current, remaining = stack.pop()
        
        # Check if we reached a leaf node with the correct path sum
        if not current.left and not current.right and remaining == 0:
            return True
        
        # Push children to the stack with updated remaining sums
        if current.right:
            stack.append((current.right, remaining - current.right.val))
        if current.left:
            stack.append((current.left, remaining - current.left.val))
    
    return False

πŸ” R β€” Review

Interviewer Prompts & Possible Answers:

  • "What edge cases should we test?"
    β†’ "An empty tree, a tree with one node, trees where no path matches, trees with negative values, and trees where multiple paths exist but only one adds up correctly."

  • "How would you verify this works with different types of trees?"
    β†’ "I'd try balanced trees, skewed trees, and trees with positive, negative, and zero values."

  • "Could you trace through a simple example?"
    β†’ "Sure, for a tree [5,4,8,11,null,13,4,7,2,null,null,null,1] with target 22: 5β†’4β†’11β†’2 gives us 5+4+11+2=22, so return True."

  • "What happens with negative numbers?"
    β†’ "Negative numbers prevent early termination optimizations, but our algorithm handles them correctly since we check the exact sum at leaf nodes."

Test Cases:

def test_hasPathSum():
    # Empty tree
    assert hasPathSum(None, 0) == False
    
    # Single node - match
    assert hasPathSum(TreeNode(5), 5) == True
    
    # Single node - no match
    assert hasPathSum(TreeNode(1), 5) == False
    
    # Complex tree with valid path
    root = TreeNode(5,
        left=TreeNode(4,
            left=TreeNode(11, TreeNode(7), TreeNode(2))
        ),
        right=TreeNode(8,
            left=TreeNode(13),
            right=TreeNode(4, right=TreeNode(1))
        )
    )
    assert hasPathSum(root, 22) == True  # 5+4+11+2=22
    assert hasPathSum(root, 26) == True  # 5+8+13=26
    assert hasPathSum(root, 18) == True  # 5+8+4+1=18
    assert hasPathSum(root, 100) == False

🧹 E β€” Evaluate & Optimize

Interviewer Prompts & Possible Answers:

  • "What's the time and space complexity of your solution?"
    β†’ "Time is O(n) since we might visit every node in the worst case. Space is O(h) where h is the tree height due to recursion stack."

  • "Could this be done iteratively?"
    β†’ "Yes, using a stack to simulate recursion and explicitly tracking the current sum along with the node."

  • "What are the tradeoffs between recursive and iterative approaches?"
    β†’ "Recursion is simpler and cleaner to write, but iterative avoids potential stack overflow issues in very deep trees."

  • "Can we optimize this further?"
    β†’ "Not really in terms of time complexity - we need to potentially check all paths. The space complexity is already optimal for the recursive approach."

  • "How does this compare to collecting all root-to-leaf sums first?"
    β†’ "Our approach is more efficient because it can return early when a valid path is found, rather than computing all possible sums."

  • "What if we needed to find all valid paths instead of just checking existence?"
    β†’ "We'd need to modify the approach to collect paths instead of returning boolean, and we couldn't use early termination."

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment