剑指offer解题报告(Java版)——树的子结构 18
引言
继续二叉树的狂轰乱炸,这道题很简单,就是一个二叉树的递归问题
分析问题
要判断树B是否为树A的子结构,可以分为两步,第一步找到两棵树中节点相同的根节点R
然后判断A中以R为根节点的子树是否包含树B,比如以下两棵树,我们知道子树B的根节点是8,所以我们在A中从根节点开始找,找8,发现根节点就是8,于是我们分别去看8的左孩子,发现A中8的左孩子是8,而B中8的左孩子是9,对不上号
于是抛弃这个8,在在左子树中寻找8,发现左孩子为8,然后也去看8的左右孩子是否能对上号,发现可以,于是返回true,如果对不上,那么遍历左右子树,寻找到8,然后匹配
解决问题
首先我们需要有一个函数去找A中的8
寻找函数
public boolean hasSubTree(BinaryTreeNode root1,BinaryTreeNode root2)
{
if(root2==null)
return true;
else
if(root1==null)
return false;
boolean result=false;
if(root1!=null && root2!=null)
{
if(root1.data==root2.data)
result=doesTree1HaveTree2(root1, root2);
if(!result)
return hasSubTree(root1.leftNode, root2) || hasSubTree(root1.rightNode, root2);
}
return result;
}
传入的参数有两个,也就是两个树的根节点,如果root2为空,那么root1肯定包含root2,返回true,如果root1为空,那么必定为false,这是Corner case,要注意检验
然后就是看root1和root2是否相等,如果相等,就去逐个比较左右孩子,这个我们另外写一个函数实现,函数返回是个布尔值,表示是否匹配成功
如果不等,我们就需要递归到左子树和右子树中去寻找了,因为每个寻找函数hasSubTree中都包含了子树匹配的函数doesTree1HaveTree2,所以我们只需要调用寻找函数就行了
接下来我们看如何逐个匹配
子树匹配
public boolean doesTree1HaveTree2(BinaryTreeNode root1,BinaryTreeNode root2)
{
if(root2==null)
return true;
else
if(root1==null)
return false;
if(root1.data!=root2.data)
return false;
else {
return doesTree1HaveTree2(root1.leftNode, root2.leftNode) && doesTree1HaveTree2(root1.rightNode, root2.rightNode);
}
}
子树匹配也是传入两个根节点,如果root2为空,说明肯定匹配上了,如果root1为空,那么说明肯定匹配不上了,这个跟刚才的一样
然后如果都不为空,就需要比较这两个根节点的值是否相等,如果不相等,那好,不用比了,肯定匹配不上,如果相等,那么需要递归到左右子树去比较了,而且必须要左右子树都能匹配上才行
测试代码
public static void main(String args[])
{
BinaryTreeNode root1=new BinaryTreeNode();
BinaryTreeNode node1=new BinaryTreeNode();
BinaryTreeNode node2=new BinaryTreeNode();
BinaryTreeNode node3=new BinaryTreeNode();
BinaryTreeNode node4=new BinaryTreeNode();
BinaryTreeNode node5=new BinaryTreeNode();
BinaryTreeNode node6=new BinaryTreeNode();
root1.leftNode=node1;
root1.rightNode=node2;
node1.leftNode=node3;
node1.rightNode=node4;
node4.leftNode=node5;
node4.rightNode=node6;
root1.data=8;
node1.data=8;
node2.data=7;
node3.data=9;
node4.data=2;
node5.data=4;
node6.data=7;
BinaryTreeNode root2=new BinaryTreeNode();
BinaryTreeNode a=new BinaryTreeNode();
BinaryTreeNode b=new BinaryTreeNode();
root2.leftNode=a;
root2.rightNode=b;
root2.data=8;
a.data=9;
b.data=2;
DoesTree1HaveTree2 test=new DoesTree1HaveTree2();
System.out.println(test.hasSubTree(root1, root2));
}