Subtree of Another Tree easy
Problem Statement
Given the roots of two binary trees root
and subRoot
, return true
if there is a subtree of root
with the same structure and node values with subRoot
and false
otherwise.
A subtree of a binary tree root
is a tree that consists of a node in root
and all of this node's descendants. The tree root
may contain multiple subtrees of the same structure and node values with subRoot
.
Example 1
Input: root = [3,4,5,1,2], subRoot = [4,1,2] Output: true
Example 2
Input: root = [3,4,5,1,2,null,null,null,null,0,6], subRoot = [4,1,2] Output: false
Steps
- Recursive Approach: We'll use a recursive approach to traverse both trees simultaneously.
- isSameTree Function: Create a helper function
isSameTree
that checks if two trees are structurally identical. This will be used recursively to compare subtrees. - isSubtree Function: The main
isSubtree
function will recursively traverseroot
. At each node, it checks if the subtree rooted at that node is identical tosubRoot
usingisSameTree
. If a match is found, it returnstrue
. Otherwise, it continues the traversal. - Base Cases:
- If
root
isnull
, returnfalse
(no subtree can be found). - If
subRoot
isnull
, returntrue
(emptysubRoot
is always a subtree). - If
root
andsubRoot
are not structurally identical, continue the traversal.
- If
- Recursive Calls: Recursively call
isSubtree
on the left and right subtrees ofroot
. - Return Value: The function returns
true
if a match is found, andfalse
otherwise.
Explanation
The isSameTree
function performs a simple depth-first traversal comparing nodes at each level. The isSubtree
function cleverly uses this to check if any subtree within the larger tree matches the structure of the smaller tree. By recursively checking at every node in the larger tree, it efficiently explores all possible subtrees.
Code
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public boolean isSubtree(TreeNode root, TreeNode subRoot) {
if (root == null) return false;
if (isSameTree(root, subRoot)) return true;
return isSubtree(root.left, subRoot) || isSubtree(root.right, subRoot);
}
private boolean isSameTree(TreeNode p, TreeNode q) {
if (p == null && q == null) return true;
if (p == null || q == null) return false;
if (p.val != q.val) return false;
return isSameTree(p.left, q.left) && isSameTree(p.right, q.right);
}
}
Complexity
- Time Complexity: O(M * N), where M is the number of nodes in
root
and N is the number of nodes insubRoot
. In the worst case, we might comparesubRoot
with every node inroot
. - Space Complexity: O(max(M, N)) in the worst case due to the recursive calls' stack depth, which can be proportional to the height of the larger tree. If the trees are highly unbalanced, the depth could be as high as the number of nodes in the largest tree.