Check if a binary tree is subtree of another binary tree | Set 2
Last Updated :
11 Oct, 2023
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.
C++
#include <cstring>
#include <iostream>
using namespace std;
#define MAX 100
struct Node {
char key;
struct Node *left, *right;
};
Node* newNode( char item)
{
Node* temp = new Node;
temp->key = item;
temp->left = temp->right = NULL;
return temp;
}
void storeInorder(Node* root, char arr[], int & i)
{
if (root == NULL) {
arr[i++] = '$' ;
return ;
}
storeInorder(root->left, arr, i);
arr[i++] = root->key;
storeInorder(root->right, arr, i);
}
void storePreOrder(Node* root, char arr[], int & i)
{
if (root == NULL) {
arr[i++] = '$' ;
return ;
}
arr[i++] = root->key;
storePreOrder(root->left, arr, i);
storePreOrder(root->right, arr, i);
}
bool isSubtree(Node* T, Node* S)
{
if (S == NULL)
return true ;
if (T == NULL)
return false ;
int m = 0, n = 0;
char inT[MAX], inS[MAX];
storeInorder(T, inT, m);
storeInorder(S, inS, n);
inT[m] = '\0' , inS[n] = '\0' ;
if ( strstr (inT, inS) == NULL)
return false ;
m = 0, n = 0;
char preT[MAX], preS[MAX];
storePreOrder(T, preT, m);
storePreOrder(S, preS, n);
preT[m] = '\0' , preS[n] = '\0' ;
return ( strstr (preT, preS) != NULL);
}
int main()
{
Node* T = newNode( 'a' );
T->left = newNode( 'b' );
T->right = newNode( 'd' );
T->left->left = newNode( 'c' );
T->right->right = newNode( 'e' );
Node* S = newNode( 'a' );
S->left = newNode( 'b' );
S->left->left = newNode( 'c' );
S->right = newNode( 'd' );
if (isSubtree(T, S))
cout << "Yes: S is a subtree of T" ;
else
cout << "No: S is NOT a subtree of T" ;
return 0;
}
|
Java
class Node {
char data;
Node left, right;
Node( char item)
{
data = item;
left = right = null ;
}
}
class Passing {
int i;
int m = 0 ;
int n = 0 ;
}
class BinaryTree {
static Node root;
Passing p = new Passing();
String strstr(String haystack, String needle)
{
if (haystack == null || needle == null ) {
return null ;
}
int hLength = haystack.length();
int nLength = needle.length();
if (hLength < nLength) {
return null ;
}
if (nLength == 0 ) {
return haystack;
}
for ( int i = 0 ; i <= hLength - nLength; i++) {
if (haystack.charAt(i) == needle.charAt( 0 )) {
int j = 0 ;
for (; j < nLength; j++) {
if (haystack.charAt(i + j) != needle.charAt(j)) {
break ;
}
}
if (j == nLength) {
return haystack.substring(i);
}
}
}
return null ;
}
void storeInorder(Node node, char arr[], Passing i)
{
if (node == null ) {
arr[i.i++] = '$' ;
return ;
}
storeInorder(node.left, arr, i);
arr[i.i++] = node.data;
storeInorder(node.right, arr, i);
}
void storePreOrder(Node node, char arr[], Passing i)
{
if (node == null ) {
arr[i.i++] = '$' ;
return ;
}
arr[i.i++] = node.data;
storePreOrder(node.left, arr, i);
storePreOrder(node.right, arr, i);
}
boolean isSubtree(Node T, Node S)
{
if (S == null ) {
return true ;
}
if (T == null ) {
return false ;
}
char inT[] = new char [ 100 ];
String op1 = String.valueOf(inT);
char inS[] = new char [ 100 ];
String op2 = String.valueOf(inS);
storeInorder(T, inT, p);
storeInorder(S, inS, p);
inT[p.m] = '\0' ;
inS[p.m] = '\0' ;
if (strstr(op1, op2) == null ) {
return false ;
}
p.m = 0 ;
p.n = 0 ;
char preT[] = new char [ 100 ];
char preS[] = new char [ 100 ];
String op3 = String.valueOf(preT);
String op4 = String.valueOf(preS);
storePreOrder(T, preT, p);
storePreOrder(S, preS, p);
preT[p.m] = '\0' ;
preS[p.n] = '\0' ;
return (strstr(op3, op4) != null );
}
public static void main(String args[])
{
BinaryTree tree = new BinaryTree();
Node T = new Node( 'a' );
T.left = new Node( 'b' );
T.right = new Node( 'd' );
T.left.left = new Node( 'c' );
T.right.right = new Node( 'e' );
Node S = new Node( 'a' );
S.left = new Node( 'b' );
S.right = new Node( 'd' );
S.left.left = new Node( 'c' );
if (tree.isSubtree(T, S)) {
System.out.println( "Yes, S is a subtree of T" );
}
else {
System.out.println( "No, S is not a subtree of T" );
}
}
}
|
Python3
MAX = 100
class Node:
def __init__( self ):
self .key = ' '
self .left = None
self .right = None
def newNode(item):
temp = Node()
temp.key = item
return temp
def storeInorder(root, i):
if (root = = None ):
return '$'
res = storeInorder(root.left, i)
res + = root.key
res + = storeInorder(root.right, i)
return res
def storePreOrder(root, i):
if (root = = None ):
return '$'
res = root.key
res + = storePreOrder(root.left, i)
res + = storePreOrder(root.right, i)
return res
def isSubtree(T, S):
if (S = = None ):
return True
if (T = = None ):
return False
m = 0
n = 0
inT = storeInorder(T, m)
inS = storeInorder(S, n)
res = True
if inS in inT :
res = True
else :
res = False
if (res = = False ):
return res
m = 0
n = 0
preT = storePreOrder(T, m)
preS = storePreOrder(S, n)
if preS in preT:
return True
else :
return False
T = newNode( 'a' )
T.left = newNode( 'b' )
T.right = newNode( 'd' )
T.left.left = newNode( 'c' )
T.right.right = newNode( 'e' )
S = newNode( 'a' )
S.left = newNode( 'b' )
S.left.left = newNode( 'c' )
S.right = newNode( 'd' )
if (isSubtree(T, S)):
print ( "Yes: S is a subtree of T" )
else :
print ( "No: S is NOT a subtree of T" )
|
C#
using System;
public class Node {
public char data;
public Node left, right;
public Node( char item)
{
data = item;
left = right = null ;
}
}
public class Passing {
public int i;
public int m = 0;
public int n = 0;
}
public class BinaryTree {
static Node root;
Passing p = new Passing();
String strstr(String haystack, String needle)
{
if (haystack == null || needle == null ) {
return null ;
}
int hLength = haystack.Length;
int nLength = needle.Length;
if (hLength < nLength) {
return null ;
}
if (nLength == 0) {
return haystack;
}
for ( int i = 0; i <= hLength - nLength; i++) {
if (haystack[i] == needle[0]) {
int j = 0;
for (; j < nLength; j++) {
if (haystack[i + j] != needle[j]) {
break ;
}
}
if (j == nLength) {
return haystack.Substring(i);
}
}
}
return null ;
}
void storeInorder(Node node, char [] arr, Passing i)
{
if (node == null ) {
arr[i.i++] = '$' ;
return ;
}
storeInorder(node.left, arr, i);
arr[i.i++] = node.data;
storeInorder(node.right, arr, i);
}
void storePreOrder(Node node, char [] arr, Passing i)
{
if (node == null ) {
arr[i.i++] = '$' ;
return ;
}
arr[i.i++] = node.data;
storePreOrder(node.left, arr, i);
storePreOrder(node.right, arr, i);
}
bool isSubtree(Node T, Node S)
{
if (S == null ) {
return true ;
}
if (T == null ) {
return false ;
}
char [] inT = new char [100];
String op1 = String.Join( "" , inT);
char [] inS = new char [100];
String op2 = String.Join( "" , inS);
storeInorder(T, inT, p);
storeInorder(S, inS, p);
inT[p.m] = '\0' ;
inS[p.m] = '\0' ;
if (strstr(op1, op2) != null ) {
return false ;
}
p.m = 0;
p.n = 0;
char [] preT = new char [100];
char [] preS = new char [100];
String op3 = String.Join( "" , preT);
String op4 = String.Join( "" , preS);
storePreOrder(T, preT, p);
storePreOrder(S, preS, p);
preT[p.m] = '\0' ;
preS[p.n] = '\0' ;
return (strstr(op3, op4) != null );
}
public static void Main(String[] args)
{
BinaryTree tree = new BinaryTree();
Node T = new Node( 'a' );
T.left = new Node( 'b' );
T.right = new Node( 'd' );
T.left.left = new Node( 'c' );
T.right.right = new Node( 'e' );
Node S = new Node( 'a' );
S.left = new Node( 'b' );
S.right = new Node( 'd' );
S.left.left = new Node( 'c' );
if (tree.isSubtree(T, S)) {
Console.WriteLine( "Yes, S is a subtree of T" );
}
else {
Console.WriteLine( "No, S is not a subtree of T" );
}
}
}
|
Javascript
<script>
const MAX = 100
class Node{
constructor(){
this .key = ' '
this .left = null
this .right = null
}
}
function newNode(item){
temp = new Node()
temp.key = item
return temp
}
function storeInorder(root, i){
if (root == null )
return '$'
res = storeInorder(root.left, i)
res += root.key
res += storeInorder(root.right, i)
return res
}
function storePreOrder(root, i){
if (root == null )
return '$'
res = root.key
res += storePreOrder(root.left, i)
res += storePreOrder(root.right, i)
return res
}
function isSubtree(T, S){
if (S == null )
return true
if (T == null )
return false
let m = 0
let n = 0
let inT = storeInorder(T, m)
let inS = storeInorder(S, n)
res = true
if (inT.indexOf(inT) !== -1)
res = true
else
res = false
if (res == false )
return res
m = 0
n = 0
let preT = storePreOrder(T, m)
let preS = storePreOrder(S, n)
if (preT.indexOf(preS) !== -1)
return true
else
return false
}
let T = new newNode( 'a' )
T.left = new newNode( 'b' )
T.right = new newNode( 'd' )
T.left.left = new newNode( 'c' )
T.right.right = new newNode( 'e' )
let S = new newNode( 'a' )
S.left = new newNode( 'b' )
S.left.left = new newNode( 'c' )
S.right = new newNode( 'd' )
if (isSubtree(T, S))
document.write( "Yes: S is a subtree of T" , "</br>" )
else
document.write( "No: S is NOT a subtree of T" , "</br>" )
</script>
|
Output
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)
EASY: String Serialisation Method & using KMP algorithm:-
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)
C++
#include <bits/stdc++.h>
using namespace std;
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)
{
string tree1, tree2;
convertPreorder(root, tree1);
convertPreorder(subRoot, tree2);
if (tree1.find(tree2) == string::npos)
return false ;
return true ;
}
void convertPreorder(TreeNode* root, string& s)
{
if (root == nullptr)
s += ",#" ;
else {
s += "," + to_string(root->val);
convertPreorder(root->left, s);
convertPreorder(root->right, s);
}
}
void inOrderTraversal(TreeNode *root)
{
if (root == NULL)
return ;
inOrderTraversal(root->left);
cout << root->val << " " ;
inOrderTraversal(root->right);
}
};
int main()
{
struct TreeNode* root = new TreeNode(3);
root->left = new TreeNode(4);
root->right = new TreeNode(5);
root->left->left = new TreeNode(1);
root->left->right = new TreeNode(2);
struct TreeNode *subRoot = new TreeNode(4);
subRoot->left = new TreeNode(1);
subRoot->right = new TreeNode(2);
class Solution myObj;
cout << "Our Tree1 and Tree2 Looks like:\n" <<endl;
cout<< "\nTree1: " ;
myObj.inOrderTraversal(root);
cout<< "\nTree2: " ;
myObj.inOrderTraversal(subRoot);
myObj.isSubtree(root,subRoot) ? cout<< "\nYes Tree2 is subroot of Tree1\n" : cout<< "\nNo Tree2 is not Subtree of Tree1\n" <<endl;
return 0;
}
|
Java
import java.util.*;
public class Solution {
public boolean isSubtree(TreeNode root, TreeNode subRoot) {
StringBuilder tree1 = new StringBuilder();
StringBuilder tree2 = new StringBuilder();
convertPreorder(root, tree1);
convertPreorder(subRoot, tree2);
if (tree1.indexOf(tree2.toString()) == - 1 )
return false ;
return true ;
}
public void convertPreorder(TreeNode root, StringBuilder s) {
if (root == null ) {
s.append( ",#" );
} else {
s.append( "," + root.val);
convertPreorder(root.left, s);
convertPreorder(root.right, s);
}
}
public void inOrderTraversal(TreeNode root) {
if (root == null )
return ;
inOrderTraversal(root.left);
System.out.print(root.val + " " );
inOrderTraversal(root.right);
}
public static void main(String[] args) {
TreeNode root = new TreeNode( 3 );
root.left = new TreeNode( 4 );
root.right = new TreeNode( 5 );
root.left.left = new TreeNode( 1 );
root.left.right = new TreeNode( 2 );
TreeNode subRoot = new TreeNode( 4 );
subRoot.left = new TreeNode( 1 );
subRoot.right = new TreeNode( 2 );
Solution myObj = new Solution();
System.out.println( "Our Tree1 and Tree2 Looks like:\n" );
System.out.print( "\nTree1: " );
myObj.inOrderTraversal(root);
System.out.print( "\nTree2: " );
myObj.inOrderTraversal(subRoot);
if (myObj.isSubtree(root, subRoot))
System.out.println( "\nYes Tree2 is subroot of Tree1\n" );
else
System.out.println( "\nNo Tree2 is not Subtree of Tree1\n" );
}
}
class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode() {
val = 0 ;
left = null ;
right = null ;
}
TreeNode( int x) {
val = x;
left = null ;
right = null ;
}
TreeNode( int x, TreeNode left, TreeNode right) {
val = x;
this .left = left;
this .right = right;
}
}
|
Python3
class TreeNode:
def __init__( self , val = 0 , left = None , right = None ):
self .val = val
self .left = left
self .right = right
class Solution:
def isSubtree( self , root: TreeNode, subRoot: TreeNode) - > bool :
tree1 = ''
tree2 = ''
self .convertPreorder(root, tree1)
self .convertPreorder(subRoot, tree2)
if tree2 not in tree1:
return False
return True
def convertPreorder( self , root: TreeNode, s: str ) - > None :
if root is None :
s + = ',#'
else :
s + = ',' + str (root.val)
self .convertPreorder(root.left, s)
self .convertPreorder(root.right, s)
def inOrderTraversal( self , root: TreeNode) - > None :
if root is None :
return
self .inOrderTraversal(root.left)
print (root.val, end = " " )
self .inOrderTraversal(root.right)
if __name__ = = '__main__' :
root = TreeNode( 3 )
root.left = TreeNode( 4 )
root.right = TreeNode( 5 )
root.left.left = TreeNode( 1 )
root.left.right = TreeNode( 2 )
|
C#
using System;
public class TreeNode
{
public int val;
public TreeNode left, right;
public TreeNode( int val = 0, TreeNode left = null , TreeNode right = null )
{
this .val = val;
this .left = left;
this .right = right;
}
}
public class Solution
{
public bool IsSubtree(TreeNode root, TreeNode subRoot)
{
string tree1 = "" , tree2 = "" ;
ConvertPreorder(root, ref tree1);
ConvertPreorder(subRoot, ref tree2);
if (!tree1.Contains(tree2))
return false ;
return true ;
}
public void ConvertPreorder(TreeNode root, ref string s)
{
if (root == null )
s += ",#" ;
else
{
s += "," + root.val;
ConvertPreorder(root.left, ref s);
ConvertPreorder(root.right, ref s);
}
}
public void InOrderTraversal(TreeNode root)
{
if (root == null )
return ;
InOrderTraversal(root.left);
Console.Write(root.val + " " );
InOrderTraversal(root.right);
}
}
public class Program
{
static void Main( string [] args)
{
TreeNode root = new TreeNode(3)
{
left = new TreeNode(4),
right = new TreeNode(5)
};
root.left.left = new TreeNode(1);
root.left.right = new TreeNode(2);
TreeNode subRoot = new TreeNode(4)
{
left = new TreeNode(1),
right = new TreeNode(2)
};
Solution myObj = new Solution();
Console.WriteLine( "Our Tree1 and Tree2 Looks like:\n" );
Console.Write( "Tree1: " );
myObj.InOrderTraversal(root);
Console.Write( "\nTree2: " );
myObj.InOrderTraversal(subRoot);
bool isSubtree = myObj.IsSubtree(root, subRoot);
Console.WriteLine(isSubtree ? "\nYes Tree2 is subtree of Tree1" : "\nNo Tree2 is not subtree of Tree1" );
}
}
|
Javascript
class TreeNode {
constructor(val) {
this .val = val;
this .left = null ;
this .right = null ;
}
}
class Solution {
isSubtree(root, subRoot) {
const tree1 = [];
const tree2 = [];
this .convertPreorder(root, tree1);
this .convertPreorder(subRoot, tree2);
const tree1String = tree1.join( "," );
const tree2String = tree2.join( "," );
if (tree1String.indexOf(tree2String) === -1)
return false ;
return true ;
}
convertPreorder(root, arr) {
if (root === null ) {
arr.push( "#" );
} else {
arr.push(root.val);
this .convertPreorder(root.left, arr);
this .convertPreorder(root.right, arr);
}
}
inOrderTraversal(root) {
if (root === null )
return ;
this .inOrderTraversal(root.left);
console.log(root.val + " " );
this .inOrderTraversal(root.right);
}
}
const root = new TreeNode(3);
root.left = new TreeNode(4);
root.right = new TreeNode(5);
root.left.left = new TreeNode(1);
root.left.right = new TreeNode(2);
const subRoot = new TreeNode(4);
subRoot.left = new TreeNode(1);
subRoot.right = new TreeNode(2);
const myObj = new Solution();
console.log( "Our Tree1 and Tree2 Looks like:\n" );
console.log( "\nTree1: " );
myObj.inOrderTraversal(root);
console.log( "\nTree2: " );
myObj.inOrderTraversal(subRoot);
if (myObj.isSubtree(root, subRoot))
console.log( "\nYes Tree2 is subroot of Tree1\n" );
else
console.log( "\nNo Tree2 is not Subtree of Tree1\n" );
|
Output
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
C++
#include <iostream>
#include <string>
#include <vector>
using namespace std;
struct TreeNode {
int val;
TreeNode* left;
TreeNode* right;
TreeNode( int x) : val(x), left(nullptr), right(nullptr) {}
};
class Solution {
public :
bool isSubtree(TreeNode* root, TreeNode* subRoot) {
return kmp(serialize(root), serialize(subRoot));
}
void inOrderTraversal(TreeNode *root)
{
if (root == NULL)
return ;
inOrderTraversal(root->left);
cout << root->val << " " ;
inOrderTraversal(root->right);
}
private :
bool kmp(string s, string p) {
vector< int > lps = getLPS(p);
int n = s.length(), m = p.length();
for ( int i = 0, j = 0; i < n; ++i) {
while (s[i] != p[j] && j > 0) j = lps[j-1];
if (s[i] == p[j]) j++;
if (j == m) return true ;
}
return false ;
}
vector< int > getLPS(string p) {
int m = p.length();
vector< int > lps(m);
for ( int i = 1, j = 0; i < m; ++i) {
while (p[i] != p[j] && j > 0) j = lps[j-1];
if (p[i] == p[j]) lps[i] = ++j;
}
return lps;
}
string serialize(TreeNode* root) {
string str;
serializeHelper(root, str);
return str;
}
void serializeHelper(TreeNode* root, string& str) {
if (!root) {
str += ",#" ;
} else {
str += "," + to_string(root->val);
serializeHelper(root->left, str);
serializeHelper(root->right, str);
}
}
};
int main()
{
struct TreeNode* root = new TreeNode(3);
root->left = new TreeNode(4);
root->right = new TreeNode(5);
root->left->left = new TreeNode(1);
root->left->right = new TreeNode(2);
struct TreeNode *subRoot = new TreeNode(4);
subRoot->left = new TreeNode(1);
subRoot->right = new TreeNode(2);
class Solution myObj;
cout << "Our Tree1 and Tree2 Looks like:\n" <<endl;
cout<< "\nTree1: " ;
myObj.inOrderTraversal(root);
cout<< "\nTree2: " ;
myObj.inOrderTraversal(subRoot);
myObj.isSubtree(root,subRoot) ? cout<< "\nYes Tree2 is subroot of Tree1\n" : cout<< "\nNo Tree2 is not Subtree of Tree1\n" <<endl;
return 0;
}
|
Java
class Solution {
public boolean isSubtree(TreeNode root, TreeNode subRoot) {
return kmp(serialize(root), serialize(subRoot));
}
boolean kmp(String s, String p) {
int [] lps = getLPS(p);
int n = s.length(), m = p.length();
for ( int i = 0 , j = 0 ; i < n; ++i) {
while (s.charAt(i) != p.charAt(j) && j > 0 ) j = lps[j- 1 ];
if (s.charAt(i) == p.charAt(j)) j++;
if (j == m) return true ;
}
return false ;
}
int [] getLPS(String p) {
int m = p.length();
int [] lps = new int [m];
for ( int i = 1 , j = 0 ; i < m; ++i) {
while (p.charAt(i) != p.charAt(j) && j > 0 ) j = lps[j- 1 ];
if (p.charAt(i) == p.charAt(j)) lps[i] = ++j;
}
return lps;
}
String serialize(TreeNode root) {
StringBuilder sb = new StringBuilder();
serialize(root, sb);
return sb.toString();
}
void serialize(TreeNode root, StringBuilder sb) {
if (root == null ) {
sb.append( ",#" );
} else {
sb.append( "," + root.val);
serialize(root.left, sb);
serialize(root.right, sb);
}
}
public void inOrderTraversal(TreeNode root) {
if (root == null )
return ;
inOrderTraversal(root.left);
System.out.print(root.val + " " );
inOrderTraversal(root.right);
}
public static void main(String[] args) {
TreeNode root = new TreeNode( 3 );
root.left = new TreeNode( 4 );
root.right = new TreeNode( 5 );
root.left.left = new TreeNode( 1 );
root.left.right = new TreeNode( 2 );
TreeNode subRoot = new TreeNode( 4 );
subRoot.left = new TreeNode( 1 );
subRoot.right = new TreeNode( 2 );
Solution myObj = new Solution();
System.out.println( "Our Tree1 and Tree2 Looks like:\n" );
System.out.print( "\nTree1: " );
myObj.inOrderTraversal(root);
System.out.print( "\nTree2: " );
myObj.inOrderTraversal(subRoot);
if (myObj.isSubtree(root, subRoot))
System.out.println( "\nYes Tree2 is subroot of Tree1\n" );
else
System.out.println( "\nNo Tree2 is not Subtree of Tree1\n" );
}
}
class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode() {
val = 0 ;
left = null ;
right = null ;
}
TreeNode( int x) {
val = x;
left = null ;
right = null ;
}
TreeNode( int x, TreeNode left, TreeNode right) {
val = x;
this .left = left;
this .right = right;
}
}
|
Python3
class TreeNode:
def __init__( self , val = 0 , left = None , right = None ):
self .val = val
self .left = left
self .right = right
class Solution:
def isSubtree( self , root: Optional[TreeNode], subRoot: Optional[TreeNode]) - > bool :
def serialize(root):
if root = = None :
return ",#"
return "," + str (root.val) + serialize(root.left) + serialize(root.right)
def getLPS(s):
m, j = len (s), 0
lps = [ 0 ] * m
for i in range ( 1 , m):
while s[i] ! = s[j] and j > 0 : j = lps[j - 1 ]
if s[i] = = s[j]:
j + = 1
lps[i] = j
return lps
def kmp(s, p):
lps = getLPS(p)
n, m, j = len (s), len (p), 0
for i in range (n):
while s[i] ! = p[j] and j > 0 : j = lps[j - 1 ]
if s[i] = = p[j]:
j + = 1
if j = = m: return True
return False
return kmp(serialize(root), serialize(subRoot))
if __name__ = = '__main__' :
root = TreeNode( 3 )
root.left = TreeNode( 4 )
root.right = TreeNode( 5 )
root.left.left = TreeNode( 1 )
root.left.right = TreeNode( 2 )
|
C#
using System;
using System.Collections.Generic;
public class TreeNode
{
public int val;
public TreeNode left;
public TreeNode right;
public TreeNode( int x) { val = x; }
}
public class Solution
{
public bool IsSubtree(TreeNode root, TreeNode subRoot)
{
return Kmp(Serialize(root), Serialize(subRoot));
}
public void InOrderTraversal(TreeNode root)
{
if (root == null )
return ;
InOrderTraversal(root.left);
Console.Write(root.val + " " );
InOrderTraversal(root.right);
}
private bool Kmp( string s, string p)
{
List< int > lps = GetLPS(p);
int n = s.Length, m = p.Length;
for ( int i = 0, j = 0; i < n; ++i)
{
while (s[i] != p[j] && j > 0) j = lps[j - 1];
if (s[i] == p[j]) j++;
if (j == m) return true ;
}
return false ;
}
private List< int > GetLPS( string p)
{
int m = p.Length;
List< int > lps = new List< int >(m);
for ( int i = 1, j = 0; i < m; ++i)
{
while (p[i] != p[j] && j > 0) j = lps[j - 1];
if (p[i] == p[j]) lps.Add(++j);
else lps.Add(0);
}
return lps;
}
private string Serialize(TreeNode root)
{
string str = "" ;
SerializeHelper(root, ref str);
return str;
}
private void SerializeHelper(TreeNode root, ref string str)
{
if (root == null )
{
str += ",#" ;
}
else
{
str += "," + root.val;
SerializeHelper(root.left, ref str);
SerializeHelper(root.right, ref str);
}
}
}
class Program
{
static void Main()
{
TreeNode root = new TreeNode(3)
{
left = new TreeNode(4)
{
left = new TreeNode(1),
right = new TreeNode(2)
},
right = new TreeNode(5)
};
TreeNode subRoot = new TreeNode(4)
{
left = new TreeNode(1),
right = new TreeNode(2)
};
Solution myObj = new Solution();
Console.WriteLine( "Our Tree1 and Tree2 Looks like:\n" );
Console.Write( "\nTree1: " );
myObj.InOrderTraversal(root);
Console.Write( "\nTree2: " );
myObj.InOrderTraversal(subRoot);
if (myObj.IsSubtree(root, subRoot))
{
Console.WriteLine( "\nYes, Tree2 is a subtree of Tree1\n" );
}
else
{
Console.WriteLine( "\nNo, Tree2 is not a subtree of Tree1\n" );
}
}
}
|
Javascript
class TreeNode {
constructor(val) {
this .val = val;
this .left = null ;
this .right = null ;
}
}
class Solution {
isSubtree(root, subRoot) {
return this .kmp( this .serialize(root), this .serialize(subRoot));
}
inOrderTraversal(root) {
if (!root) return ;
this .inOrderTraversal(root.left);
console.log(root.val + " " );
this .inOrderTraversal(root.right);
}
kmp(s, p) {
const lps = this .getLPS(p);
const n = s.length, m = p.length;
for (let i = 0, j = 0; i < n; ++i) {
while (s[i] !== p[j] && j > 0) j = lps[j-1];
if (s[i] === p[j]) j++;
if (j === m) return true ;
}
return false ;
}
getLPS(p) {
const m = p.length;
const lps = new Array(m);
for (let i = 1, j = 0; i < m; ++i) {
while (p[i] !== p[j] && j > 0) j = lps[j-1];
if (p[i] === p[j]) lps[i] = ++j;
}
return lps;
}
serialize(root) {
const str = [];
this .serializeHelper(root, str);
return str.join( "," );
}
serializeHelper(root, str) {
if (!root) {
str.push( "#" );
} else {
str.push(root.val.toString());
this .serializeHelper(root.left, str);
this .serializeHelper(root.right, str);
}
}
}
const root = new TreeNode(3);
root.left = new TreeNode(4);
root.right = new TreeNode(5);
root.left.left = new TreeNode(1);
root.left.right = new TreeNode(2);
const subRoot = new TreeNode(4);
subRoot.left = new TreeNode(1);
subRoot.right = new TreeNode(2);
const myObj = new Solution();
console.log( "Our Tree1 and Tree2 Looks like:\n" );
console.log( "Tree1: " );
myObj.inOrderTraversal(root);
console.log( "\nTree2: " );
myObj.inOrderTraversal(subRoot);
myObj.isSubtree(root, subRoot) ? console.log( "\nYes Tree2 is subroot of Tree1\n" ) : console.log( "\nNo Tree2 is not Subtree of Tree1\n" );
|
Output
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)
Please Login to comment...