Skip to content

Instantly share code, notes, and snippets.

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

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

Select an option

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

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

https://leetcode.com/problems/same-tree/

πŸ“Œ Problem Statement

Given the roots of two binary trees p and q,
Return True if they are the same tree, False otherwise.

Two binary trees are considered the same if they are structurally identical, and the nodes have the same value.


🧭 U β€” Understand the Problem

Interviewer Prompts & Possible Answers:

  • "Can you restate the problem in your own words?"
    β†’ "We need to check if two binary trees are exactly the same - same structure and same values at corresponding positions."

  • "What does 'structurally identical' mean?"
    β†’ "The trees have the same shape - where one tree has a node, the other must also have a node, and where one has null, the other must have null."

  • "Do the values need to match as well?"
    β†’ "Yes, corresponding nodes must have the same value. Both structure and values must be identical."

  • "What if both trees are empty?"
    β†’ "Two empty trees are considered the same, so we should return True."

  • "What if one tree is empty and the other isn't?"
    β†’ "They're definitely not the same, so return False."

  • "Does the order of children matter?"
    β†’ "Yes, left child of one tree must correspond to left child of the other tree, same for right children."


πŸ§ͺ M β€” Match with Patterns

Interviewer Prompts & Possible Answers:

  • "What traversal pattern would work well here?"
    β†’ "Any traversal could work, but we can actually check nodes as we go rather than collecting all values first."

  • "Have you seen similar problems involving tree comparison?"
    β†’ "Yes, like checking if a tree is symmetric, or finding if one tree is a subtree of another."

  • "Do you think recursion or iteration would be better?"
    β†’ "Recursion fits naturally since we're comparing corresponding nodes in both trees simultaneously."

  • "What's the key insight for this problem?"
    β†’ "We can solve this by recursively checking if corresponding nodes are equal, and if their left and right subtrees are also the same."

  • "How does this relate to tree traversal algorithms?"
    β†’ "It's like doing a synchronized traversal of both trees, where we compare nodes at each step."


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

Interviewer Prompts & Possible Answers:

  • "What would be your base cases for recursion?"
    β†’ "If both nodes are null, return True. If one is null and the other isn't, return False. If both exist but have different values, return False."

  • "How would you handle the recursive case?"
    β†’ "If the current nodes are equal, recursively check if their left subtrees are the same AND their right subtrees are the same."

  • "Could you outline the algorithm step by step?"
    β†’ "1. Check if both nodes are null (same). 2. Check if one is null but not the other (different). 3. Check if values are different (different). 4. Recursively check left subtrees and right subtrees."

  • "Why do you need to check both left and right subtrees?"
    β†’ "Both subtrees must be identical for the trees to be the same. If either subtree differs, the trees are different."

  • "What's the logical condition for returning True?"
    β†’ "Current nodes must have the same value AND left subtrees must be the same AND right subtrees must be the same."


⌨️ 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 isSameTree(p: TreeNode, q: TreeNode) -> bool:
    # Base case: both nodes are None
    if p is None and q is None:
        return True
    
    # Base case: one node is None, the other isn't
    if p is None or q is None:
        return False
    
    # Base case: nodes have different values
    if p.val != q.val:
        return False
    
    # Recursive case: check left and right subtrees
    return (isSameTree(p.left, q.left) and 
            isSameTree(p.right, q.right))

Compact Recursive Solution

def isSameTree(p: TreeNode, q: TreeNode) -> bool:
    # Handle all base cases in one condition
    if not p and not q:
        return True
    if not p or not q or p.val != q.val:
        return False
    
    # Recursive case
    return (isSameTree(p.left, q.left) and 
            isSameTree(p.right, q.right))

Iterative Solution (Alternative)

def isSameTree(p: TreeNode, q: TreeNode) -> bool:
    # Use a stack to simulate recursion
    stack = [(p, q)]
    
    while stack:
        node1, node2 = stack.pop()
        
        # Both are None - continue
        if not node1 and not node2:
            continue
        
        # One is None or values differ - trees are different
        if not node1 or not node2 or node1.val != node2.val:
            return False
        
        # Add children to stack for comparison
        stack.append((node1.left, node2.left))
        stack.append((node1.right, node2.right))
    
    return True

Using Deque for BFS Approach

from collections import deque

def isSameTree(p: TreeNode, q: TreeNode) -> bool:
    queue = deque([(p, q)])
    
    while queue:
        node1, node2 = queue.popleft()
        
        if not node1 and not node2:
            continue
        
        if not node1 or not node2 or node1.val != node2.val:
            return False
        
        queue.append((node1.left, node2.left))
        queue.append((node1.right, node2.right))
    
    return True

πŸ” R β€” Review

Interviewer Prompts & Possible Answers:

  • "What edge cases should we test?"
    β†’ "Both trees empty, one tree empty, single node trees (same and different values), trees with same values but different structure, completely different trees."

  • "How would you trace through an example?"
    β†’ "For trees [1,2,3] and [1,2,3]: Compare roots (1==1 βœ“), compare left subtrees (2==2 βœ“), compare right subtrees (3==3 βœ“), return True."

  • "What about trees that look the same but have different structure?"
    β†’ "Like [1,2] vs [1,null,2]? The first has 2 as left child, the second has 2 as right child. Our algorithm will catch this when comparing left subtrees."

  • "Could you write some test cases?"

def test_isSameTree():
    # Both empty
    assert isSameTree(None, None) == True
    
    # One empty, one not
    assert isSameTree(None, TreeNode(1)) == False
    assert isSameTree(TreeNode(1), None) == False
    
    # Single nodes - same
    assert isSameTree(TreeNode(1), TreeNode(1)) == True
    
    # Single nodes - different
    assert isSameTree(TreeNode(1), TreeNode(2)) == False
    
    # Same structure and values
    tree1 = TreeNode(1, TreeNode(2), TreeNode(3))
    tree2 = TreeNode(1, TreeNode(2), TreeNode(3))
    assert isSameTree(tree1, tree2) == True
    
    # Same values, different structure
    tree3 = TreeNode(1, TreeNode(2), None)
    tree4 = TreeNode(1, None, TreeNode(2))
    assert isSameTree(tree3, tree4) == False
    
    # Different values
    tree5 = TreeNode(1, TreeNode(2), TreeNode(1))
    tree6 = TreeNode(1, TreeNode(1), TreeNode(2))
    assert isSameTree(tree5, tree6) == False

🧹 E β€” Evaluate & Optimize

Interviewer Prompts & Possible Answers:

  • "What's the time and space complexity?"
    β†’ "Time: O(min(m,n)) where m and n are the number of nodes in each tree, since we stop as soon as we find a difference. Space: O(min(m,n)) for recursion stack in worst case."

  • "Why is it min(m,n) and not m+n?"
    β†’ "We're traversing both trees simultaneously and stop early if we find any difference. In the worst case (identical trees), we visit all nodes of the smaller tree."

  • "Which approach do you prefer - recursive or iterative?"
    β†’ "Recursive is cleaner and more intuitive for tree problems. Iterative might be better for very deep trees to avoid stack overflow."

  • "Is there any way to optimize this further?"
    β†’ "Not really in terms of asymptotic complexity. We need to potentially check every corresponding node pair. Early termination when differences are found is already optimal."

  • "How does this compare to serializing both trees and comparing strings?"
    β†’ "String comparison would work but is less efficient in space (need to store entire serialization) and time (no early termination). Direct comparison is better."

  • "What if we needed to find all differences instead of just checking equality?"
    β†’ "We'd need to continue traversing even after finding differences and collect all mismatched nodes. The current approach can't be easily modified for this."

  • "How would you handle very large trees?"
    β†’ "For memory-constrained environments, the iterative approach might be preferable to avoid deep recursion stacks. Could also implement tail recursion optimization."

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