Problem
Given the roots of two binary trees p
and q
, write a function to check if they are the same or not.
Two binary trees are considered the same if they are structurally identical, and the nodes have the same value.
Example
Input: Two binary Search Trees
Check if Two Binary Tree’s are Identical
Example 1:
p =
1
/ \
2 3
q =
1
/ \
2 3
Input: p = [1,2,3], q = [1,2,3]
Output: true
Solution
Method 1 - Recursive
Algorithm
- Recursive Traversal: Begin by traversing both trees simultaneously from their roots.
- Match Check: If either root is null or their data doesn’t match, return
false
(structural or value mismatch). - Subtree Verification: Recursively check if
p.left
is a subtree ofq.left
andp.right
is a subtree ofq.right
. - Completion Consistency: If one tree finishes traversing (null) while the other has nodes, return
false
(structural difference). - Match Confirmation: If both trees reach the end simultaneously (both null), return
true
(trees match).
Code
Java
public boolean isSameTree(TreeNode p, TreeNode q) {
if (p == null && q == null) {
return true;
}
if (p == null || q == null) {
return false;
}
return p.val == q.val &&
isSameTree(p.left, q.left) &&
isSameTree(p.right, q.right);
}
Rust
use std::rc::Rc;
use std::cell::RefCell;
impl Solution {
pub fn is_same_tree(p: Option<Rc<RefCell<TreeNode>>>, q: Option<Rc<RefCell<TreeNode>>>) -> bool {
match (p, q) {
(None, None) => true,
(Some(p), Some(q)) => {
let p = p.borrow();
let q = q.borrow();
p.val == q.val
&& Self::is_same_tree(p.left.clone(), q.left.clone())
&& Self::is_same_tree(p.right.clone(), q.right.clone())
}
_ => false,
}
}
}
A regular rust user would see this line
#[derive(Debug, PartialEq, Eq)]
pub struct TreeNode {
and deduce that Eq
is already derive
d for TreeNode
and hence the equivalence of TreeNode
can just as simple as p == q
pub fn is_same_tree(p: Option<Rc<RefCell<TreeNode>>>, q: Option<Rc<RefCell<TreeNode>>>) -> bool {
p == q
}
Method 2 - Iterative using Level Order Traversal
Code
Go
func isSameTree(p *TreeNode, q *TreeNode) bool {
type Pair struct {
p, q *TreeNode
}
var queue []Pair
queue = append(traverse, Pair{p, q})
for len(traverse) > 0 {
pair := queue[len(traverse) - 1]
traverse = queue[:len(traverse) - 1]
if pair.p != nil && pair.q != nil && pair.p.Val == pair.q.Val {
traverse = append(traverse, Pair{pair.p.Left, pair.q.Left})
traverse = append(traverse, Pair{pair.p.Right, pair.q.Right})
} else if pair.p != nil || pair.q != nil {
return false
}
}
return true
}
Java
public boolean isSameTree(TreeNode p, TreeNode q) {
Queue<TreeNode> queue1 = new LinkedList<>();
Queue<TreeNode> queue2 = new LinkedList<>();
queue1.offer(p);
queue2.offer(q);
while (!queue1.isEmpty() && !queue2.isEmpty()) {
TreeNode node1 = queue1.poll();
TreeNode node2 = queue2.poll();
if (node1 == null && node2 == null) {
continue;
}
if (node1 == null || node2 == null || node1.val != node2.val) {
return false;
}
queue1.offer(node1.left);
queue1.offer(node1.right);
queue2.offer(node2.left);
queue2.offer(node2.right);
}
return queue1.isEmpty() && queue2.isEmpty();
}
Rust
use std::rc::Rc;
use std::cell::RefCell;
impl Solution {
pub fn is_same_tree(p: Option<Rc<RefCell<TreeNode>>>, q: Option<Rc<RefCell<TreeNode>>>) -> bool {
let mut queue = Vec::new();
queue.push((p, q));
while let Some((mut p, mut q)) = queue.pop() {
if p.is_none() != q.is_none() {
return false
} else if let (Some(p), Some(q)) = (p.take(), q.take()) {
let (mut p, mut q) = (p.borrow_mut(), q.borrow_mut());
if p.val != q.val {
return false
}
queue.push((p.left.take(), q.left.take()));
queue.push((p.right.take(), q.right.take()));
}
}
true
}
}
Method 3 - Iterative using DFS
Code
Java
public boolean isSameTree(TreeNode p, TreeNode q) {
Stack<TreeNode> stack1 = new Stack<>();
Stack<TreeNode> stack2 = new Stack<>();
stack1.push(p);
stack2.push(q);
while (!stack1.isEmpty() && !stack2.isEmpty()) {
TreeNode node1 = stack1.pop();
TreeNode node2 = stack2.pop();
if (node1 == null && node2 == null) {
continue;
} else if (node1 == null || node2 == null || node1.val != node2.val) {
return false;
}
stack1.push(node1.left);
stack2.push(node2.left);
stack1.push(node1.right);
stack2.push(node2.right);
}
return stack1.isEmpty() && stack2.isEmpty();
}