题目
原文:
You have two very 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.
译文:
有两个非常大的二叉树:T1,有上百万个结点,T2,有上百个结点。创建一个算法判断T2是否是T1的子树。
解答
方法1:用常规的暴力方法, 先在T1中找到T2的根结点,然后依次去匹配它们的左右子树即可。但是要注意的一点是,T1中的结点可能包含多个与T2根结点的值相同的结点。因此, 在T1中查找T2的根结点时,如果找到与T2匹配的子树,则返回真值;否则,还要继续查找, 直到在T1中找到一棵匹配的子树或是T1中的结点都查找完毕。
方法2:对T1,T2中的每个节点生成一个hash值,hash值由当前节点和左右子树共同决定;
完整代码如下:
import java.util.HashSet; class Q4_7{ //暴力法 public static boolean method0(TreeNode tn1,TreeNode tn2){ if(tn2==null) return true; else return subtree(tn1,tn2); } private static boolean subtree(TreeNode tn1,TreeNode tn2){ if(tn1==null) return false; else if(tn1.value==tn2.value){ if(match(tn1,tn2)) return true; } else return subtree(tn1.lchild,tn2)||subtree(tn1.rchild,tn2); return false; } private static boolean match(TreeNode tn1,TreeNode tn2){ if(tn1==null&&tn2==null) return true; else if(tn1==null||tn2==null) return false; else if(tn1.value!=tn2.value) return false; else return match(tn1.lchild,tn2.lchild)&&match(tn1.rchild,tn2.rchild); } //对二叉树每个节点生成一个hash值 public static boolean method1(TreeNode tn1,TreeNode tn2){ hash(tn1); hash(tn2); HashSet<Integer> set=new HashSet<Integer>(); preTraverse(tn1,set); if(set.contains(tn2.hashValue)) return true; else return false; } private static void preTraverse(TreeNode tn1,HashSet<Integer> set){ if(tn1==null) return; set.add(tn1.hashValue); preTraverse(tn1.lchild,set); preTraverse(tn1.rchild,set); } private static int hash(TreeNode tnode){ if(tnode==null) return 0; if(tnode.lchild==null&&tnode.rchild==null) tnode.hashValue=tnode.value; else tnode.hashValue=3*tnode.value+5*hash(tnode.lchild)+7*hash(tnode.rchild); return tnode.hashValue; } public static void main(String[] args){ int[] arr1 = {5,1,3,8,6,10}; int[] arr2 = {8,6,10}; TreeNode t1 = TreeNode.createBinaryTree(arr1); TreeNode t2 = TreeNode.createBinaryTree(arr2); System.out.println(method0(t1,t2)); System.out.println(method1(t1,t2)); } } class TreeNode{ int value; TreeNode lchild; TreeNode rchild; TreeNode parent; int hashValue; public static void insert(TreeNode tnode,int x,TreeNode p){ if(tnode==null){ tnode=new TreeNode(); tnode.value=x; tnode.lchild=null; tnode.rchild=null; if(p.value>x) p.lchild=tnode; else p.rchild=tnode; tnode.parent=p; return; } if(x<tnode.value){ insert(tnode.lchild,x,tnode); }else{ insert(tnode.rchild,x,tnode); } } public static TreeNode createBinaryTree(int[] values){ TreeNode root=new TreeNode(); root.value=values[0]; for(int i=1;i<values.length;i++){ insert(root,values[i],root); } return root; } }