Check if a binary tree is subtree of another binary tree | GeeksforGeeks
Given two binary trees, check if the first tree is 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.
Solution: Traverse the tree T in preorder fashion. For every visited node in the traversal, see if the subtree rooted with this node is identical to S.
Time Complexity: Time worst case complexity of above solution is O(mn) where m and n are number of nodes in given two trees.
http://www.geeksforgeeks.org/check-binary-tree-subtree-another-binary-tree-set-2/
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.
1) Find inorder and preorder traversals of T, store them in two auxiliary arrays inT[] and preT[].
2) Find inorder and preorder traversals of S, 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.
The above algorithm doesn't work for cases where a tree is present in another tree, but not as a subtree.
The above algorithm can be extended to handle such cases by adding a special character whenever we encounter NULL in inorder and preorder traversals.
Time Complexity: Inorder and Preorder traversals of Binary Tree take O(n) time. The functionstrstr() can also be implemented in O(n) time using KMP string matching algorithm.
http://www.jiuzhang.com/solutions/subtree/
Should use LinkedList<String> or StringBuilder.
public String inOrder(Node root, String i){
if(root!=null){
return inOrder(root.left,i) + " " + root.data + " " +inOrder(root.right,i);
}
return "";
}
public String postOrder(Node root, String i){
if(root!=null){
return postOrder(root.left,i) + " " + postOrder(root.right,i) + " " + root.data;
}
return "";
}
public boolean checkSubtree(Node rootA, Node rootB){
String inOrderA = inOrder(rootA,"");
String inOrderB = inOrder(rootB,"");
String postOrderA = postOrder(rootA,"");
String postOrderB = postOrder(rootB,"");
return (inOrderA.toLowerCase().contains(inOrderB.toLowerCase()) && postOrderA.toLowerCase().contains(postOrderB.toLowerCase()));
}
http://www.codebytes.in/2015/01/checking-if-given-binary-tree-is-sub.html ===>not good solution
1. Traverse T1, find nodes that match the root of T2.
2. For all the nodes that match, check if the trees with those roots are equivalent.
Tl and T2 are two very large binary trees, with Tl much bigger than T2. Create an
algorithm to determine ifT2 is a subtree of Tl.
A tree T2 is a subtree of Tl if there exists a node n in Tl such that the subtree of n is identical to T2.
That is, if you cut off the tree at node n, the two trees would be identical.
This approach takes O(n + m) time and O(n + m) space,
boolean containsTree(TreeNode tl, TreeNode t2) {
StringBuilder stringl = new StringBuilder();
StringBuilder string2 = new StringBuilder();
getOrderString(tl, s tringl);
getOrderString(t2, string2);
return stringl.indexOf(string2.toString()) != -1;
}
void getOrderString(TreeNode node, StringBuilder sb) {
if (node == null) {
sb.append ( "X"); / / Add null indicator
return;
}
sb.append (node.data + " "); / / Add root
getOrderString(node.left, sb); // Add left
getOrderString(node.right, sb); // Add right
}
An alternative approach is to search through the larger tree, Tl. Each time a node in Tl matches the root
ofT2, call match Tree. The match Tree method will compare the two subtrees to see if they are identical.
boolean containsTree(TreeNode tl, TreeNode t2) {
if (t2 == null) return true; // The empty tree is always a subtree
return subTree(tl, t2);
}
boolean subTree(TreeNode rl, TreeNode r2) {
if (rl == null) {
return false; // big tree empty & subtree still not found.
} else if (rl.data == r2.data && matchTree(rl, r2)) {
return true;
}
return subTree(rl.left, r2) || subTree(rl.right, r2);
}
boolean matchTree(TreeNode rl, TreeNode r2) {
if (rl == null && r2 == null) {
return true; // nothing left in the subtree
} else if (rl == null || r2 == null) {
return false; // exactly tree is empty, therefore trees dones't match
} else if (rl.data != r2.data) {
return false; // data doesn't match
} else {
return matchTree(rl.left, r2.left) && matchTree(rl.right, r2.right);
}
}
https://reeestart.wordpress.com/2016/06/14/google-is-subtree/
https://discuss.leetcode.com/topic/18/check-if-a-binary-tree-is-a-subtree-of-another-binary-tree/11
Read full article from Check if a binary tree is subtree of another binary tree | GeeksforGeeks
Given two binary trees, check if the first tree is 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.
Solution: Traverse the tree T in preorder fashion. For every visited node in the traversal, see if the subtree rooted with this node is identical to S.
Time Complexity: Time worst case complexity of above solution is O(mn) where m and n are number of nodes in given two trees.
static
Node root1,root2;
/* A utility function to check whether trees with roots as root1 and
root2 are identical or not */
boolean
areIdentical(Node node1, Node node2) {
/* base cases */
if
(node1 ==
null
&& node2 ==
null
) {
return
true
;
}
if
(node1 ==
null
|| node2 ==
null
) {
return
false
;
}
/* Check if the data of both roots is same and data of left and right
subtrees are also same */
return
(node1.data == node2.data
&& areIdentical(node1.left, node2.left)
&& areIdentical(node1.right, node2.right));
}
/* This function returns true if S is a subtree of T, otherwise false */
boolean
isSubtree(Node T, Node S) {
/* base cases */
if
(S ==
null
) {
return
true
;
}
if
(T ==
null
) {
return
false
;
}
/* Check the tree with root as current node */
if
(areIdentical(T, S)) {
return
true
;
}
/* If the tree with root as current node doesn't match then
try left and right subtrees one by one */
return
isSubtree(T.left, S)
|| isSubtree(T.right, S);
}
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.
1) Find inorder and preorder traversals of T, store them in two auxiliary arrays inT[] and preT[].
2) Find inorder and preorder traversals of S, 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.
The above algorithm doesn't work for cases where a tree is present in another tree, but not as a subtree.
The above algorithm can be extended to handle such cases by adding a special character whenever we encounter NULL in inorder and preorder traversals.
Time Complexity: Inorder and Preorder traversals of Binary Tree take O(n) time. The functionstrstr() can also be implemented in O(n) time using KMP string matching algorithm.
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. Inorder and Preorder traversals of small tree or Tree1 are 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.
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
;
}
// A utility function to store inorder traversal of tree rooted
// with root in an array arr[]. Note that i is passed as reference
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);
}
// A utility function to store preorder traversal of tree rooted
// with root in an array arr[]. Note that i is passed as reference
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);
}
/* This function returns true if S is a subtree of T, otherwise false */
boolean
isSubtree(Node T, Node S) {
/* base cases */
if
(S ==
null
) {
return
true
;
}
if
(T ==
null
) {
return
false
;
}
// Store Inorder traversals of T and S in inT[0..m-1]
// and inS[0..n-1] respectively
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 inS[] is not a substring of preS[], return false
if
(strstr(op1, op2) !=
null
) {
return
false
;
}
// Store Preorder traversals of T and S in inT[0..m-1]
// and inS[0..n-1] respectively
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'
;
// If inS[] is not a substring of preS[], return false
// Else return true
return
(strstr(op3, op4) !=
null
);
}
http://www.jiuzhang.com/solutions/subtree/
public boolean isSubtree(TreeNode T1, TreeNode T2) { if (T2 == null) { return true; } if (T1 == null) { return false; } if (isEqual(T1, T2)) { return true; } if (isSubtree(T1.left, T2) || isSubtree(T1.right, T2)) { return true; } return false; } private boolean isEqual(TreeNode T1, TreeNode T2) { if (T1 == null || T2 == null) { return T1 == T2; } if (T1.val != T2.val) { return false; } return isEqual(T1.left, T2.left) && isEqual(T1.right, T2.right); }http://lintcode.peqiu.com/content/lintcode/subtree.html
首先是特殊情况的处理,然后是树的遍历,可以用栈或者递归,对于判断两个树是否相等,用递归的方式,用栈的话需要同时入出栈,比较麻烦
bool isSubtree(TreeNode *T1, TreeNode *T2) {
// write your code here
if (!T2) {
return true;
} else if (!T1) { // !T1 && T2
return false;
}
stack tmp;
tmp.push(T1);
while(!tmp.empty()) {
TreeNode* pNode = tmp.top();
if(isSubtreeHelper(pNode, T2))
return true;
tmp.pop();
if(pNode->right)
tmp.push(pNode->right);
if(pNode->left)
tmp.push(pNode->left);
}
return false;
}
bool isSubtreeHelper(TreeNode *T1, TreeNode *T2) {
if (!T1 && !T2) {
return true;
}
if (T1 && T2) {
return T1->val == T2->val &&
isSubtreeHelper(T1->left, T2->left) &&
isSubtreeHelper(T1->right, T2->right);
}
return false;
}
http://algorithms.tutorialhorizon.com/given-two-binary-trees-check-if-one-binary-tree-is-a-subtree-of-another/Should use LinkedList<String> or StringBuilder.
public String inOrder(Node root, String i){
if(root!=null){
return inOrder(root.left,i) + " " + root.data + " " +inOrder(root.right,i);
}
return "";
}
public String postOrder(Node root, String i){
if(root!=null){
return postOrder(root.left,i) + " " + postOrder(root.right,i) + " " + root.data;
}
return "";
}
public boolean checkSubtree(Node rootA, Node rootB){
String inOrderA = inOrder(rootA,"");
String inOrderB = inOrder(rootB,"");
String postOrderA = postOrder(rootA,"");
String postOrderB = postOrder(rootB,"");
return (inOrderA.toLowerCase().contains(inOrderB.toLowerCase()) && postOrderA.toLowerCase().contains(postOrderB.toLowerCase()));
}
http://www.codebytes.in/2015/01/checking-if-given-binary-tree-is-sub.html ===>not good solution
1. Traverse T1, find nodes that match the root of T2.
2. For all the nodes that match, check if the trees with those roots are equivalent.
private void getIdenticals(Node node, Node B, List<Node> store){ if(node==null) return; if(node.equals(B)) store.add(node); getIdenticals(node.left, B, store); getIdenticals(node.right, B, store); } public boolean isSubtree(Node root, Node B){ if(root == null || B == null)return false; List<Node> possibleNodes = new ArrayList<>(); getIdenticals(root, B, possibleNodes); for(Node n:possibleNodes) if(match(n, B))return true; return false; } private boolean match(Node head, Node B){ if(head==null && B == null)return true; if(head==null || B == null)return false; if(head.equals(B)){ if(match(head.left, B.left) && match(head.right, B.right)) return true; } return false; }
Tl and T2 are two very large binary trees, with Tl much bigger than T2. Create an
algorithm to determine ifT2 is a subtree of Tl.
A tree T2 is a subtree of Tl if there exists a node n in Tl such that the subtree of n is identical to T2.
That is, if you cut off the tree at node n, the two trees would be identical.
boolean containsTree(TreeNode tl, TreeNode t2) {
StringBuilder stringl = new StringBuilder();
StringBuilder string2 = new StringBuilder();
getOrderString(tl, s tringl);
getOrderString(t2, string2);
return stringl.indexOf(string2.toString()) != -1;
}
void getOrderString(TreeNode node, StringBuilder sb) {
if (node == null) {
sb.append ( "X"); / / Add null indicator
return;
}
sb.append (node.data + " "); / / Add root
getOrderString(node.left, sb); // Add left
getOrderString(node.right, sb); // Add right
}
An alternative approach is to search through the larger tree, Tl. Each time a node in Tl matches the root
ofT2, call match Tree. The match Tree method will compare the two subtrees to see if they are identical.
boolean containsTree(TreeNode tl, TreeNode t2) {
if (t2 == null) return true; // The empty tree is always a subtree
return subTree(tl, t2);
}
boolean subTree(TreeNode rl, TreeNode r2) {
if (rl == null) {
return false; // big tree empty & subtree still not found.
} else if (rl.data == r2.data && matchTree(rl, r2)) {
return true;
}
return subTree(rl.left, r2) || subTree(rl.right, r2);
}
boolean matchTree(TreeNode rl, TreeNode r2) {
if (rl == null && r2 == null) {
return true; // nothing left in the subtree
} else if (rl == null || r2 == null) {
return false; // exactly tree is empty, therefore trees dones't match
} else if (rl.data != r2.data) {
return false; // data doesn't match
} else {
return matchTree(rl.left, r2.left) && matchTree(rl.right, r2.right);
}
}
https://reeestart.wordpress.com/2016/06/14/google-is-subtree/
不算难的一道题,一看就是递归。但是注意分析这道题的时间复杂度,不是O(n)喔。如果是递归的做法,应该是O(n^2)。而且也有两种递归方式,一种直接递归找subtree,另一种借助isSame()
[Solution #2]
当然这题也有O(n)的解法,对两个tree的任意两种order traversal做KMP. 不包括level order!!
当然这题也有O(n)的解法,对两个tree的任意两种order traversal做KMP. 不包括level order!!
// O(n^2) time 直接递归
class
Solution {
public
boolean
isSubtree(TreeNode s, TreeNode t) {
if
(s ==
null
) {
return
true
;
}
if
(t ==
null
) {
return
false
;
}
return
dfs(s, t);
}
private
boolean
dfs(TreeNode s, TreeNode t) {
if
(s ==
null
&& t ==
null
) {
return
true
;
}
if
(s ==
null
|| t ==
null
) {
return
false
;
}
boolean
result =
false
;
if
(s.val == t.val) {
result |= dfs(s.left, t.left) && dfs(s.right, t.right);
}
result |= dfs(s, t.left);
result |= dfs(s, t.right);
return
result;
}
}
// O(n^2) time 借助isSame() 来递归
class
Solution2 {
public
boolean
isSubtree(TreeNode s, TreeNode t) {
if
(s ==
null
) {
return
true
;
}
if
(t ==
null
) {
return
false
;
}
if
(isSame(s, t)) {
return
true
;
}
return
isSubtree(s, t.left) || isSubtree(s, t.right);
}
private
boolean
isSame(TreeNode s, TreeNode t) {
if
(s ==
null
&& t ==
null
) {
return
true
;
}
if
(s ==
null
|| t ==
null
) {
return
false
;
}
if
(s.val != t.val) {
return
false
;
}
return
isSame(s.left, t.left) && isSame(s.right, t.right);
}
}
Read full article from Check if a binary tree is subtree of another binary tree | GeeksforGeeks