https://leetcode.com/problems/same-tree/
Given the roots of two binary trees
pandq,
ReturnTrueif they are the same tree,Falseotherwise.Two binary trees are considered the same if they are structurally identical, and the nodes have the same value.
-
"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 returnTrue." -
"What if one tree is empty and the other isn't?"
β "They're definitely not the same, so returnFalse." -
"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."
-
"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."
-
"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."
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))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))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 Truefrom 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-
"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-
"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."