之前做了剑指offer的“树的子结构”和牛客网算法课“拓扑相同的子树”,发觉这其中还是有些微妙的地方需要注意的,总结如下:
树的子结构和树的子树问题:
子树的意思是包含了一个结点,就得包含这个结点下的所有节点,一棵大小为n的二叉树有n个子树,就是分别以每个结点为根的子树。子结构的意思是包含了一个结点,可以只取左子树或者右子树,或者都不取。
如下图,二叉树2是二叉树1的子树也是子结构,但是二叉树3只是二叉树1的子结构但不是子树。
也就是说判断一个二叉树是否为另一二叉树的子树的时候,需要所搜索到叶子节点,即从根节点及其左右子树的节点都要相同。而判断一个二叉树是否为另一颗二叉树的子结构的时候,不一定需要到达叶子节点,其对应结构节点相同即可。
题目一:剑指offer
输入两棵二叉树A,B,判断B是不是A的子结构。(ps:我们约定空树不是任意一个树的子结构)
class Solution {
public:
bool HasSubtree(TreeNode* pRoot1, TreeNode* pRoot2)
{
bool result=false;
if(pRoot1!=NULL&&pRoot2!=NULL)
{
if(pRoot1->val==pRoot2->val)
{
result=isInclude(pRoot1,pRoot2);
}
if(!result) result=isInclude(pRoot1->left,pRoot2);
if(!result) result=isInclude(pRoot1->right,pRoot2);
}
return result;
}
private:
bool isInclude(TreeNode* pRoot1,TreeNode* pRoot2)
{
if(pRoot2==NULL) return true;//子树先到达叶子节点返回true
if(pRoot1==NULL) return false;//父树先到达叶子节点返回false
if(pRoot1->val!=pRoot2->val) return false;
return isInclude(pRoot1->left,pRoot2->left)&&isInclude(pRoot1->right,pRoot2->right);//分别搜索左子树和右子树
}
};
题目二:牛客网算法课(树的子树)
对于两棵彼此独立的二叉树A和B,请编写一个高效算法,检查A中是否存在一棵子树与B树的拓扑结构完全相同。给定两棵二叉树的头结点A和B,请返回一个bool值,代表A中是否存在一棵同构于B的子树。
class IdenticalTree {
public:
bool chkIdentical(TreeNode* A, TreeNode* B) {
// write code here
bool res=false;
if(A!=NULL&&B!=NULL)
{
if(A->val==B->val)
res=IsAHasB(A,B);
if(!res)
res=chkIdentical(A->left,B);
if(!res)
res=chkIdentical(A->right,B);
}
return res;
}
bool IsAHasB(TreeNode* A,TreeNode* B)//需要一直遍历到叶子节点
{
if(A==NULL&&B!=NULL) return false;
if(A!=NULL&&B==NULL) return false;//当任何一个树先到达叶子节点,返回false
if(A==NULL&&B==NULL) return true;//同时到达叶子节点,返回true
if(A->val!=B->val) return false;
return IsAHasB(A->left,B->left)&&IsAHasB(A->right,B->right);
}
};