剑指Offer 26 树的子结构
题目描述: 输入两棵二叉树A和B,判断B是不是A的子结构。(约定空树不是任意一个树的子结构) B是A的子结构, 即 A中有出现和B相同的结构和节点值。LeetCode链接
首先,这个题要和判断B树是不是A树的子树区分
- 如下左图所示,t 既是s的子结构也是s的子树
- 如下右图所示,t只是s的子结构而不是s的子树(因为t不包含s中以4为根节点子树的全部,即0号节点)
**过程分析:**如果B是A的子结构,那么就需要判断A树中以任意一个节点为根的子树有没有包含B,因此就要遍历A树的每一个节点Na,然后判断以Na为根的子树有没有包含B树。
具体过程:
-
首先判断两个树的 根节点A、B是否为空,如果A或B为空,或者AB均为空,那么B一定不是A的子结构
-
如果AB均不为空,分三种情况讨论
-
以A为根节点的子树包含B
-
以A的左孩子为根节点的子树包含B
-
以A的右孩子为根节点的子树包含B
-
-
判断当前节点为根的子树是否包含B
-
如果B为空,说明B树已经遍历结束,匹配成功
如下所示,当B指向①,即B为空时,说明B已经遍历结束,那么说明A树中以当前节点为根的子树包含B
-
如果A为空(B不为空),说明A中不包含这个节点,匹配失败
如下图所示,当B指向①,B为3,但是②已经为空,那么说明A树中以当前节点为根的子树不包含B
-
如果AB均不为空,判断其值是否相同
-
如果不同,匹配失败
如下所示,当AB均不为空,但其值不同,那么说明A树中以当前节点为根的子树不包含B
-
如果相同,判断当A的左孩子和B的左孩子是否有相同子结构,并且还要判断A的右孩子和B的右孩子是否有相同子结构,依次递归。如果两者子树均相同,那么说明A树中以当前节点为根的子树包含B。
-
-
代码实现:
public boolean isSubStructure(TreeNode A, TreeNode B)
{
//根据题意,如果A为空 或 B为空 或AB均为空(两个是空树),则一定不是子结构
if (A == null || B == null)
{
return false;
}
//如果以节点A为根节点的子树包含树B 或者 以节点A的左孩子为根节点的子树包含树B 或者 以节点A的右孩子为根节点的子树包含树B
return isSameTree(A, B) || isSubStructure(A.left, B) || isSubStructure(A.right, B);
}
public static boolean isSameTree(TreeNode aNode, TreeNode B)
{
//如果B为空,说明B树已经匹配完成
if (B == null)
{
return true;
}
//如果a为空,b不为空或者ab均不为空,但其值不同,说明匹配失败
if (aNode == null || aNode.val != B.val)
{
return false;
}
//如果ab均不为空,且值相同,递归判断其叶子节点
return isSameTree(aNode.left, B.left) && isSameTree(aNode.right, B.right);
}