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的子树。

解答

方法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;
	}
}

---EOF---

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值