This approach involves using a recursive function to traverse the root tree and checking for a matching subtree starting from every node. A helper function can be used to check if trees rooted at specific nodes are identical.
Time Complexity: O(N*M), where N is the number of nodes in the root tree and M is the number of nodes in subRoot tree.
Space Complexity: O(min(N, M)), depending on the tree height during recursion.
1#include <bits/stdc++.h>
2using namespace std;
3
4struct TreeNode {
5 int val;
6 TreeNode *left, *right;
7};
8
9bool isIdentical(TreeNode* s, TreeNode* t) {
10 if (!s && !t) return true;
11 if (!s || !t) return false;
12 return (s->val == t->val) && isIdentical(s->left, t->left) && isIdentical(s->right, t->right);
13}
14
15bool isSubtree(TreeNode* root, TreeNode* subRoot) {
16 if (!root) return false;
17 if (isIdentical(root, subRoot)) return true;
18 return isSubtree(root->left, subRoot) || isSubtree(root->right, subRoot);
19}
This solution uses the same logic as the C solution, with helper functions isIdentical
and isSubtree
to recursively match subtrees or check subtrees under left and right children.
Another approach to solving this problem is by converting the trees into their preorder traversal strings with marker symbols for nulls, and then checking if the subRoot string is a substring of the root string.
Time Complexity: O(N + M + N*M), where N and M are the sizes of the trees.
Space Complexity: O(N + M), for the preorder traversal strings.
1var isSubtree = function(root, subRoot) {
2 const rootStr = preorder(root).join(' ');
3 const subRootStr = preorder(subRoot).join(' ');
4 return rootStr.indexOf(subRootStr) !== -1;
5};
6
7var preorder = function(node) {
8 if (!node) {
9 return ['null'];
10 }
11 return [node.val.toString(), ...preorder(node.left), ...preorder(node.right)];
12};
This solution generates a preorder traversal string array including 'null' for both trees, concatenates them, and checks if subRoot's string is a substring of root's.