![]() |
VOOZH | about |
Given two binary trees, check if the first tree is a subtree of the second one. A subtree of a tree T is a tree S consisting of a node in T and all of its descendants in T.
The subtree corresponding to the root node is the entire tree; the subtree corresponding to any other node is called a proper subtree.
For example, in the following case, Tree1 is a subtree of Tree2.
Tree1
x
/ \
a b
\
c
Tree2
z
/ \
x e
/ \ \
a b k
\
c
We have discussed an O(n2) solution for this problem. In this post, the O(n) solution is discussed. The idea is based on the fact that inorder and preorder/postorder uniquely identify a binary tree. Tree S is a subtree of T if both inorder and preorder traversals of S are substrings of inorder and preorder traversals of T respectively.
Following are detailed steps.
1) Find inorder and preorder traversals of T, and store them in two auxiliary arrays inT[] and preT[].
2) Find inorder and preorder traversals of S, and store them in two auxiliary arrays inS[] and preS[].
3) If inS[] is a subarray of inT[] and preS[] is a subarray preT[], then S is a subtree of T. Else not.
We can also use postorder traversal in place of preorder in the above algorithm.
Let us consider the above example
Inorder and Preorder traversals of the big tree are.
inT[] = {a, c, x, b, z, e, k}
preT[] = {z, x, a, c, b, e, k}
Inorder and Preorder traversals of small tree are
inS[] = {a, c, x, b}
preS[] = {x, a, c, b}
We can easily figure out that inS[] is a subarray of
inT[] and preS[] is a subarray of preT[].
EDIT
The above algorithm doesn't work for cases where a tree is present
in another tree, but not as a subtree. Consider the following example.
Tree1
x
/ \
a b
/
c
Tree2
x
/ \
a b
/ \
c d
Inorder and Preorder traversals of the big tree or Tree2 are.
inT[] = {c, a, x, b, d}
preT[] = {x, a, c, b, d}
Inorder and Preorder traversals of small tree or Tree1 are-
inS[] = {c, a, x, b}
preS[] = {x, a, c, b}
The Tree2 is not a subtree of Tree1, but inS[] and preS[] are
subarrays of inT[] and preT[] respectively.
The above algorithm can be extended to handle such cases by adding a special character whenever we encounter NULL in inorder and preorder traversals. Thanks to Shivam Goel for suggesting this extension.
Following is the implementation of the above algorithm.
No: S is NOT a subtree of T
Time Complexity: Inorder and Preorder traversals of Binary Tree take O(n) time. The function strstr() can also be implemented in O(n) time using the KMP string matching algorithm.
Auxiliary Space: O(n)
The method is pretty similar to the String-Matching algorithms here the approach is to store the preorder of root and sub root into two strings and then find the str_subtroot in str_root if it is present return true otherwise false.
Below I am attaching the whole program to perform the above implementation I hope it is easy to understand
Algorithm :
1. Store the inorder traversal of root in tree1
2. Similarly store the inorder traversal of subRoot in tree2
3. Search tree2 in tree1 if its present return true otherwise false
Note : You can use any other string matching algorithm such as KMP algorithm, Boyer Moore Searching, Trie | (Insert and Search)
Our Tree1 and Tree2 Looks like: Tree1: 1 4 2 3 5 Tree2: 1 4 2 Yes Tree2 is subroot of Tree1
Traversal taking O(n) and since we are also storing into the string for checking its consuming O(n) space where n represents the no. of node values
Time Complexity : O(n)
Auxiliary Space: O(n)
Interviewer: can you perform even better?
Yes we can use the KMP algorithm for string searching
Prerequisites : Please check the KMP algorithm first click here
Here is the implementation code using the KMP algorithm
Our Tree1 and Tree2 Looks like: Tree1: 1 4 2 3 5 Tree2: 1 4 2 Yes Tree2 is subroot of Tree1
Time Complexity : O(n)
Auxiliary Space : O(n)