Cracking the coding interview--Q4.7
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的子树。
X.
X. http://blog.csdn.net/navyifanr/article/details/19234825
方法2:对T1,T2中的每个节点生成一个hash值,hash值由当前节点和左右子树共同决定;
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的子树。
X.
我觉得这道题目意欲考察如何在二叉树中结点数量非常巨大的情况下进行快速的查找与匹配, 不过除了常规的暴力法,我暂时想不到什么高效的方法。暴力法就很简单了, 先在T1中找到T2的根结点,然后依次去匹配它们的左右子树即可。
这里要注意的一点是,T1中的结点可能包含多个与T2根结点的值相同的结点。因此, 在T1中查找T2的根结点时,如果找到与T2匹配的子树,则返回真值;否则,还要继续查找, 直到在T1中找到一棵匹配的子树或是T1中的结点都查找完毕。
bool match(Node* r1, Node* r2){
if(r1 == NULL && r2 == NULL) return true;
else if(r1 == NULL || r2 == NULL) return false;
else if(r1->key != r2->key) return false;
else return match(r1->lchild, r2->lchild) && match(r1->rchild, r2->rchild);
}
bool subtree(Node* r1, Node* r2){
if(r1 == NULL) return false;
else if(r1->key == r2->key){
if(match(r1, r2)) return true;
}
else return subtree(r1->lchild, r2) || subtree(r1->rchild, r2);
}
bool contain_tree(Node* r1, Node* r2){
if(r2 == NULL) return true;
else return subtree(r1, r2);
}
X. http://blog.csdn.net/navyifanr/article/details/19234825
方法2:对T1,T2中的每个节点生成一个hash值,hash值由当前节点和左右子树共同决定;
- //对二叉树每个节点生成一个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;
- }
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;
- }
- }
把T1,T2两颗树转换成字符串,如[head.data [左子树] [右子树]],同时左右子树以相同的方法转换。
如果左子树或者右子树存在一颗并且只为一颗子树为空,则该子树设置为[null],这样就能区分左子树或者右子树
然后判断T2是否为T1的子串即可。
- public static String tranceString(Node_4_6 node) {
- if(node == null) {
- return "[null]";
- } else {
- if(node.lchild!=null || node.rchild!=null) {
- return "[" + node.data + tranceString(node.lchild) + tranceString(node.rchild) + "]";
- } else {
- return "[" + node.data + "]";
- }
- }
- }
- public static void main(String args[]) {
- String pattern2 = tranceString(t2Parent);
- System.out.println(pattern1.contains(pattern2));
- }