You have two every large binary trees: T1, with millions of nodes, and T2, with hundreds of nodes. Create an algorithm to decide if T2 is a subtree of T1. Have you met this question in a real interview? Yes Example T2 is a subtree of T1 in the following case: 1 3 / / T1 = 2 3 T2 = 4 / 4 T2 isn't a subtree of T1 in the following case: 1 3 / T1 = 2 3 T2 = 4 / 4 Note A tree T2 is a subtree of T1 if there exists a node n in T1 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.
方法1: 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.
1 /** 2 * Definition of TreeNode: 3 * public class TreeNode { 4 * public int val; 5 * public TreeNode left, right; 6 * public TreeNode(int val) { 7 * this.val = val; 8 * this.left = this.right = null; 9 * } 10 * } 11 */ 12 public class Solution { 13 /** 14 * @param T1, T2: The roots of binary tree. 15 * @return: True if T2 is a subtree of T1, or false. 16 */ 17 public boolean isSubtree(TreeNode T1, TreeNode T2) { 18 // write your code here 19 if (T2 == null) return true; 20 if (T1 == null) return false; 21 if (isSameTree(T1, T2)) return true; 22 return isSubtree(T1.left, T2) || isSubtree(T1.right, T2); 23 } 24 25 public boolean isSameTree(TreeNode T1, TreeNode T2) { 26 if (T1==null && T2==null) return true; 27 if (T1==null || T2==null) return false; 28 if (T1.val != T2.val) return false; 29 return isSameTree(T1.left, T2.left) && isSameTree(T1.right, T2.right); 30 } 31 }
方法2:
In this post a 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 arew substrings of inorder and preorder traversals of T respectively.
Following are detailed steps.
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.
We can also use postorder traversal in place of preorder in the above algorithm.
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 KMP string matching algorithm.
Auxiliary Space: O(n)
可惜没有过Lintcode big case
1 /** 2 * Definition of TreeNode: 3 * public class TreeNode { 4 * public int val; 5 * public TreeNode left, right; 6 * public TreeNode(int val) { 7 * this.val = val; 8 * this.left = this.right = null; 9 * } 10 * } 11 */ 12 public class Solution { 13 /** 14 * @param T1, T2: The roots of binary tree. 15 * @return: True if T2 is a subtree of T1, or false. 16 */ 17 public boolean isSubtree(TreeNode T1, TreeNode T2) { 18 // write your code here 19 if (T2 == null) return true; 20 if (T1 == null) return false; 21 StringBuffer in1 = new StringBuffer(); 22 StringBuffer in2 = new StringBuffer(); 23 inorder(in1, T1); 24 inorder(in2, T2); 25 StringBuffer pre1 = new StringBuffer(); 26 StringBuffer pre2 = new StringBuffer(); 27 preorder(pre1, T1); 28 preorder(pre2, T2); 29 return isSubstring(in2.toString(), in1.toString()) && isSubstring(pre2.toString(), pre1.toString()); 30 } 31 32 public void inorder(StringBuffer sb, TreeNode cur) { 33 if (cur == null) return; 34 inorder(sb, cur.left); 35 sb.append(cur.val); 36 inorder(sb, cur.right); 37 } 38 39 public void preorder(StringBuffer sb, TreeNode cur) { 40 if (cur == null) return; 41 sb.append(cur.val); 42 preorder(sb, cur.left); 43 preorder(sb, cur.right); 44 } 45 46 public boolean isSubstring(String str2, String str1) { 47 for (int i=0; i<=str1.length()-str2.length(); i++) { 48 String sub = str1.substring(i, i+str2.length()); 49 if (sub.equals(str2)) return true; 50 } 51 return false; 52 } 53 }