Same Tree

Same Tree looks easy. You just check if two trees are equal, right? But the interviewer wants to see if you can walk two trees at the same time and keep them in step. That careful side-by-side walk is the real test here.

🎯 The Problem

You get two binary trees. A binary tree is a structure where each node has a value and up to two children, a left child and a right child. Say if the two trees are exactly the same.

The rules:

  • β€œSame” means the same shape and the same values in the same places.
  • If one tree has a node where the other has nothing, they are not the same.
  • If both have a node in the same spot but the values differ, they are not the same.
  • Return true only when shape and values match everywhere.
Input:
Tree p Tree q
1 1
/ \ / \
2 3 2 3
Output: true
Explanation: Both trees have the same shape and the same values.

Here is a quick look at the two trees side by side. The shape and values must match at every spot.

p: 1

2

3

q: 1

2

3

🐒 Approach 1: Flatten Both Trees to Lists (Brute Force)

Turn each tree into a list, then compare the two lists.

The idea:

  • Write down every value in a fixed order.
  • Include the empty spots so the shape is recorded.
  • Do this for both trees.

How it works:

  • Compare the two lists item by item.
  • Equal lists mean the trees match.

Why it is weak:

  • You still walk both trees fully to build the lists.
  • You pay extra memory for two whole lists.
  • It adds a step without saving any work.

Here is the flatten-and-compare code:

same_tree_flatten.py
def is_same_tree(p, q):
def flat(node):
if not node: return [None]
return [node.val] + flat(node.left) + flat(node.right)
return flat(p) == flat(q)

⚑ Approach 2: Compare As You Walk With Recursion (Best)

The idea in one line: walk both trees together and compare each pair of nodes as you go.

The idea:

  • This is recursion. A function that calls itself on smaller pieces of the same problem.
  • Either both nodes are empty or both exist.
  • If both exist, their values must match.
  • Then their left sides must match, and their right sides too.

How it works:

  • Compare the current pair.
  • Ask the same question about the left children.
  • Ask it about the right children.
  • Return true only when the value and both sides match.

Why it is fast:

  • One pass. Each node is visited once.
  • It stops early the moment any pair differs.

Here is the direct recursion code:

same_tree_recursion.py
def is_same_tree(p, q):
if not p or not q:
return p is q
return p.val == q.val and is_same_tree(p.left, q.left) and is_same_tree(p.right, q.right)

πŸ” Approach 3: Compare As You Walk With a Queue (Alternative)

The idea in one line: same compare, but use a queue of node pairs instead of letting the function call itself.

The idea:

  • A queue is a line where you add at the back and remove from the front.
  • Hold pairs of nodes to check, not single nodes.

How it works:

  • Pop a pair and compare it.
  • Push the left pair and the right pair to the back.
  • Keep going until the queue is empty or a pair differs.

Why use it:

  • Same result as the recursion.
  • It avoids deep recursion on a very tall tree.
  • It is just longer to write than the recursive version.

The solution below shows how the recursion fans out across the tree.

compare(1, 1)

compare(2, 2)

compare(3, 3)

compare(null, null) = true

compare(null, null) = true

compare(null, null) = true

compare(null, null) = true

Steps to Solve

  1. If both nodes are empty, they match. Return true.
  2. If only one node is empty, they differ. Return false.
  3. If the two values are not equal, return false.
  4. Recurse on the left children of both nodes.
  5. Recurse on the right children of both nodes.
  6. Return true only when the current values match and both sides match.

This Python version uses a tiny class for the node and a recursive function.

same_tree.py
class Node:
def __init__(self, val):
self.val = val
self.left = None
self.right = None
def is_same_tree(p, q):
if p is None and q is None: # both empty: match
return True
if p is None or q is None: # one empty: differ
return False
if p.val != q.val: # values differ
return False
return is_same_tree(p.left, q.left) and \
is_same_tree(p.right, q.right) # both sides must match
p = Node(1)
p.left = Node(2)
p.right = Node(3)
q = Node(1)
q.left = Node(2)
q.right = Node(3)
print(is_same_tree(p, q))

The output of the above code will be:

True

Let us walk through the Python version line by line so you see why each line is there.

The function starts with if p is None and q is None: return True. This is the happy base case. A base case is the simplest input where recursion stops without calling itself again. If we walked off the bottom of both trees at the same spot, they match here.

Next is if p is None or q is None: return False. We already know they are not both empty. So if one is empty now, only one is. That means the shapes differ. We stop with false.

Then if p.val != q.val: return False. Both nodes exist here. If their values are not equal, the trees differ at this spot. We stop.

Finally return is_same_tree(p.left, q.left) and is_same_tree(p.right, q.right). The current pair matched. So now we ask the same question about the left children, then about the right children. The and means both sides must come back true for this spot to be true.

⏱️ Time and Space Complexity

Both the recursive and iterative ways visit every node once. So the time is O(n), where n is the number of nodes. The recursion uses memory for the call stack, which goes as deep as the tree is tall. So the space is O(h), where h is the height of the tree. For a balanced tree that is small. For a long thin tree it can reach O(n).

Approach Time Complexity Space Complexity
Flatten to lists (brute force) O(n) O(n)
Recursive compare O(n) O(h)
Iterative with a queue O(n) O(n)

Tip

Always check the empty cases first. If you compare values before checking for empty nodes, your code will crash when it reads a value from an empty node. Order matters here.

🧩 Key Takeaways

  • βœ… Walk both trees together, comparing one pair of nodes at a time.
  • βœ… Two nodes match when both are empty, or both exist with equal values and matching sides.
  • βœ… Check the empty cases before you read any value, or the code crashes.
  • βœ… The recursion fans out to the left side and the right side at every step.
  • βœ… Time is O(n) and the recursion depth is O(h), the height of the tree.

Check Your Knowledge

4 questions Show quiz Hide quiz

Test what you learned. Pick an answer for each question, then click Check.

  1. 1

    When do two nodes count as a match in the Same Tree check?

    Why: A pair matches if both are empty, or both exist with equal values and matching subtrees.

  2. 2

    Why must you check for empty nodes before comparing values?

    Why: If you read .val from an empty (null) node, the program crashes, so the empty check must come first.

  3. 3

    What is the time complexity of comparing two trees this way?

    Why: Each node is visited once, so the time is O(n) where n is the number of nodes.

  4. 4

    What does the space complexity O(h) refer to in the recursive solution?

    Why: The call stack goes as deep as the tree is tall, so the extra space is O(h), the height.

πŸš€ What’s Next?