The “Same Tree” problem is a classic interview question that tests your understanding of tree traversal. It asks:
Given two binary trees, check if they are structurally identical and node values are equal.
In this post, we'll walk through three elegant solutions:
- Recursive (DFS)
- Iterative with Queue (BFS)
- Iterative with Stack (DFS)
By the end, you'll know when and why to choose each one.
📘 Problem Statement
You are given the roots of two binary trees p and q. Return true if the two trees are the same, otherwise return false.
Two binary trees are considered the same if:
- They are structurally identical
- Corresponding nodes have the same value
🧠 Approach 1: Recursive (Depth-First Search)
This is the cleanest and most natural solution.
✅ Logic:
- If both nodes are null, returntrue
- If one is nullor values don’t match, returnfalse
- Recurse on the left and right children
🧾 Code:
var isSameTree = function (p, q) {
    if (p == null && q == null) return true;
    if (p == null || q == null || p.val !== q.val) return false;
    return isSameTree(p.left, q.left) && isSameTree(p.right, q.right);
};
⏱️ Time Complexity:
O(n) – visit every node once
💾 Space Complexity:
O(h) – due to recursion stack
- Worst case (skewed tree): O(n)
- Best case (balanced): O(log n)
🔁 Approach 2: Iterative with Queue (Breadth-First Search)
This approach uses two queues and processes both trees level by level.
✅ Logic:
- Use two queues: one for each tree
- At each step, compare the nodes
- Enqueue their children in the same order
🧾 Code:
var isSameTree = function (p, q) {
    let queue1 = [p], queue2 = [q];
    while (queue1.length && queue2.length) {
        let node1 = queue1.shift();
        let node2 = queue2.shift();
        if (!node1 && !node2) continue;
        if (!node1 || !node2 || node1.val !== node2.val) return false;
        queue1.push(node1.left, node1.right);
        queue2.push(node2.left, node2.right);
    }
    return queue1.length === 0 && queue2.length === 0;
};
⏱️ Time Complexity:
O(n) – all nodes are visited once
💾 Space Complexity:
O(n) – due to the queue holding nodes
🧱 Approach 3: Iterative with Stack (Depth-First Search)
This simulates recursion using a manual stack.
✅ Logic:
- Use a stack to store pairs of nodes
- Pop the top pair and compare them
- Push their children (right first, then left)
🧾 Code:
var isSameTree = function (p, q) {
    const stack = [[p, q]];
    while (stack.length > 0) {
        const [node1, node2] = stack.pop();
        if (!node1 && !node2) continue;
        if (!node1 || !node2 || node1.val !== node2.val) return false;
        stack.push([node1.right, node2.right]);
        stack.push([node1.left, node2.left]);
    }
    return true;
};
⏱️ Time Complexity:
O(n) – visiting every node
💾 Space Complexity:
O(h) – similar to recursion
🧮 Comparison Table
| Feature | Recursive DFS | Iterative BFS (Queue) | Iterative DFS (Stack) | 
|---|---|---|---|
| Traversal Order | Depth-First | Breadth-First | Depth-First | 
| Time Complexity | O(n) | O(n) | O(n) | 
| Space Complexity | O(h) | O(n) | O(h) | 
| Readability | ✅ Cleanest | ❌ Slightly verbose | ⚖️ Middle ground | 
| Risk of Stack Overflow | ❌ Yes (deep tree) | ✅ No | ✅ No | 
✨ Final Thoughts
Each approach is valid, and the right one depends on the situation:
- Use recursion when you want elegant, readable code and the tree isn’t too deep.
- Use queue (BFS) if you want to process nodes level-by-level or avoid recursion limits.
- Use stack (DFS) if you want control like recursion without call stack overhead.
 

 
    
Top comments (0)