鉴于二叉树的子树及二叉树的子结构问题,现总结如下:
什么是二叉树的子结构及子树?
子树的意思是包含了一个结点,就得包含这个结点下的所有节点,一棵大小为n的二叉树有n个子树,就是分别以每个结点为根的子树。子结构的意思是包含了一个结点,可以只取左子树或者右子树,或者都不取。
题目
1、输入两颗二叉树A,B,判断B是不是A的子结构。(PS:我们约定空树不是任意一个树的子结构)。
2、给定两个二叉树T1和T2,返回T1的某个子树结构是否与T2的结构相等。
思路
一、要查找树A中是否存在和树B结构一样的子结构,我们可以分为两步:
第一步在树A中找到和B的根结点的值一样的结点R,
第二步再判断树A中以R为根节点的子树是不是包含和树B一样的结构。
使用递归的方法即可。
注意
这道题目不能利用先序遍历两个树拼接成数组之后利用kmp算法寻找一个数组是否包含另一个,因为只有拓扑 结构的子树才能够满足上述条件,例如
前序为:1 2 4 # # 3 # #
1 2 # # 3 # #
二、子树
常规思路是遍历二叉树,判断是否匹配,这里使用KMP字符串匹配的思想。
1、将二叉树结构匹配问题转换成字符串匹配问题。
2、二叉树转换成字符串。将二叉树每个节点的值后面都添加一个特殊符号作为划定值边界的符号,如“_”,空节 点用 另 一 个特殊符号表示,如“#”,两个二叉树就转换为两个字符串。
3、然后将转换为字符串的两棵树用KMP字符串进行匹配即可。
/*
struct TreeNode {
int val;
struct TreeNode *left;
struct TreeNode *right;
TreeNode(int x) :
val(x), left(NULL), right(NULL) {
}
};*/
class Solution
{
public:
//子结构
bool HasSubtree(TreeNode* rootA, TreeNode* rootB)
{
if (rootA == nullptr || rootB == nullptr)
return false;
bool result = false;
if (rootA != nullptr && rootB != nullptr)
{
if (rootA->val == rootB->val)
result = ifAhasB(rootA, rootB);
if (!result)
result = HasSubtree(rootA->left, rootB);
if (!result)
result = HasSubtree(rootA->right, rootB);
}
return result;
}
private:
bool ifAhasB(TreeNode * rootA, TreeNode *rootB)
{
if (rootB == nullptr)
return true;
if (rootA == nullptr)
return false;
if (rootA->val != rootB->val)
return false;
return ifAhasB(rootA->left, rootB->left) && ifAhasB(rootA->right, rootB->right);
}
};