100. Same Tree - Explanation

Problem Link

Description

Given the roots of two binary trees p and q, return true if the trees are equivalent, otherwise return false.

Two binary trees are considered equivalent if they share the exact same structure and the nodes have the same values.

Example 1:

Input: p = [1,2,3], q = [1,2,3]

Output: true

Example 2:

Input: p = [4,7], q = [4,null,7]

Output: false

Example 3:

Input: p = [1,2,3], q = [1,3,2]

Output: false

Constraints:

  • 0 <= The number of nodes in both trees <= 100.
  • -100 <= Node.val <= 100


Topics

Recommended Time & Space Complexity

You should aim for a solution with O(n) time and O(n) space, where n is the number of nodes in the tree.


Hint 1

Can you think of an algorithm that is used to traverse the tree? Maybe in terms of recursion.


Hint 2

We can use the Depth First Search (DFS) algorithm to traverse the tree. Can you think of a way to simultaneously traverse both the trees?


Hint 3

We traverse both trees starting from their root nodes. At each step in the recursion, we check if the current nodes in both trees are either null or have the same value. If one node is null while the other is not, or if their values differ, we return false. If the values match, we recursively check their left and right subtrees. If any recursive call returns false, the result for the current recursive call is false.


Company Tags

Please upgrade to NeetCode Pro to view company tags.



Prerequisites

Before attempting this problem, you should be comfortable with:

  • Binary tree structure - Understanding nodes with left/right children and null references
  • Tree traversal (DFS) - Recursively visiting nodes in a binary tree
  • Recursion - Using recursive function calls to process tree structures
  • Base case handling - Properly handling null nodes as termination conditions

Intuition

Two binary trees are the same if:

  1. Their structure is identical.
  2. Their corresponding nodes have the same values.

So at every position:

  • If both nodes are null → they match.
  • If one is null but the other isn't → mismatch.
  • If both exist but values differ → mismatch.
  • Otherwise, compare their left subtrees and right subtrees recursively.

This is a direct structural + value-based DFS comparison.

Algorithm

  1. If both p and q are null, return true.
  2. If only one is null, return false.
  3. If their values differ, return false.
  4. Recursively compare:
    • p.left with q.left
    • p.right with q.right
  5. Return true only if both subtree comparisons are true.
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right

class Solution:
    def isSameTree(self, p: Optional[TreeNode], q: Optional[TreeNode]) -> bool:
        if not p and not q:
            return True
        if p and q and p.val == q.val:
            return self.isSameTree(p.left, q.left) and self.isSameTree(p.right, q.right)
        else:
            return False

Time & Space Complexity

  • Time complexity: O(n)O(n)
  • Space complexity: O(n)O(n)

Where nn is the number of nodes in the tree and hh is the height of the tree.


2. Iterative DFS

Intuition

Instead of using recursion, we can use an explicit stack to compare the two trees.
Each stack entry contains a pair of nodes—one from each tree—that should match.

For every pair:

  • If both are null, they match → continue.
  • If only one is null, or their values differ → trees are not the same.
  • If they match, push their children in the same order:
    • Left child pair
    • Right child pair

If we finish processing all pairs with no mismatch, the trees are identical.

Algorithm

  1. Initialize a stack with the pair (p, q).
  2. While the stack is not empty:
    • Pop a pair (node1, node2).
    • If both are null, continue.
    • If exactly one is null, return false.
    • If node1.val != node2.val, return false.
    • Push:
      • (node1.left, node2.left)
      • (node1.right, node2.right)
  3. After the loop finishes, return true (all nodes matched).
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right

class Solution:
    def isSameTree(self, p: Optional[TreeNode], q: Optional[TreeNode]) -> bool:
        stack = [(p, q)]

        while stack:
            node1, node2 = stack.pop()

            if not node1 and not node2:
                continue
            if not node1 or not node2 or node1.val != node2.val:
                return False

            stack.append((node1.right, node2.right))
            stack.append((node1.left, node2.left))

        return True

Time & Space Complexity

  • Time complexity: O(n)O(n)
  • Space complexity: O(n)O(n)

Intuition

BFS (level-order traversal) lets us compare the two trees level by level.
We maintain two queues—one for each tree. At every step, we remove a pair of nodes
that should match:

  • If both nodes are null, they match → continue.
  • If only one is null, or their values differ → trees are not the same.
  • If they match, we push their children into their respective queues
    in the same order: left child first, then right child.

Algorithm

  1. Initialize two queues:
    • q1 containing the root of the first tree.
    • q2 containing the root of the second tree.
  2. While both queues are non-empty:
    • Pop one node from each queue: nodeP, nodeQ.
    • If both are null, continue.
    • If only one is null, return false.
    • If their values differ, return false.
    • Enqueue their children:
      • Left children of both trees.
      • Right children of both trees.
  3. After BFS completes with no mismatch, return true.
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right

class Solution:
    def isSameTree(self, p: Optional[TreeNode], q: Optional[TreeNode]) -> bool:
        q1 = deque([p])
        q2 = deque([q])

        while q1 and q2:
            for _ in range(len(q1)):
                nodeP = q1.popleft()
                nodeQ = q2.popleft()

                if nodeP is None and nodeQ is None:
                    continue
                if nodeP is None or nodeQ is None or nodeP.val != nodeQ.val:
                    return False

                q1.append(nodeP.left)
                q1.append(nodeP.right)
                q2.append(nodeQ.left)
                q2.append(nodeQ.right)

        return True

Time & Space Complexity

  • Time complexity: O(n)O(n)
  • Space complexity: O(n)O(n)

Common Pitfalls

Incorrect Null Check Order

A common mistake is checking node values before verifying both nodes exist. If one node is null and you access its value, you get a null pointer exception. Always check if both nodes are null first, then if exactly one is null, before comparing values.

Comparing Only Values Without Structure

Some solutions compare just the values using traversals like inorder or preorder, ignoring tree structure. Two trees can have identical traversal sequences but different structures. You must verify both the values and the structural positions match at every node.