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 as 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 as 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], subRoot = [4,1,2] Output: false
Steps
- Recursive Check: The core idea is to recursively check if the subtree rooted at each node in
root
matchessubRoot
. - Base Cases:
- If
subRoot
is empty (nullptr
), it's considered a match (an empty subtree is a subtree of any tree). - If
root
is empty (nullptr
) andsubRoot
is not, there's no match.
- If
- Recursive Calls: If both
root
andsubRoot
are not empty, compare their values. If they match, recursively compare their left and right subtrees. - Subtree Check: If the values match and the recursive checks for the left and right subtrees return
true
, we've found a matching subtree. - Iterate Through
root
: The function iterates through each node inroot
as a potential starting point for a matching subtree.
Explanation
The solution uses a recursive helper function isSameTree
to compare two trees for structural and value equality. The main function then iterates through the nodes of the root
tree, using isSameTree
to check if the subtree starting at each node matches subRoot
. If a match is found, it returns true
; otherwise, after checking all nodes, it returns false
.
Code
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
bool isSubtree(TreeNode* root, TreeNode* subRoot) {
if (subRoot == nullptr) return true; // Empty subRoot always matches
if (root == nullptr) return false; // root empty, subRoot not empty, no match
// Check if the subtree rooted at the current node matches subRoot
if (isSameTree(root, subRoot)) return true;
// Recursively check left and right subtrees
return isSubtree(root->left, subRoot) || isSubtree(root->right, subRoot);
}
bool isSameTree(TreeNode* p, TreeNode* q) {
if (p == nullptr && q == nullptr) return true;
if (p == nullptr || q == nullptr) return false;
return (p->val == q->val) && isSameTree(p->left, q->left) && isSameTree(p->right, q->right);
}
};
Complexity
- Time Complexity: O(M * N), where N is the number of nodes in
root
and M is the number of nodes insubRoot
. In the worst case, we might comparesubRoot
with every subtree inroot
. - Space Complexity: O(max(H1, H2)), where H1 is the height of
root
and H2 is the height ofsubRoot
. This space is used for the recursion stack. In the worst case, this could be proportional to the height of the larger tree.