题目描述:
输入两棵二叉树A,B,判断B是不是A的子结构。(ps:我们约定空树不是任意一个树的子结构)
测试用例:
功能测试(树AB都是普通的二叉树;树B是或不是树A的子结构)
特殊输入测试(两颗树的一个或两个的根节点为nullptr;二叉树的所有节点都没有左子树或者右子树)
解题思路:
1)使用递归调用
分成两步:第一步,在树A中找到与树B的根节点值一样的节点R(实质上是树的遍历);第二步,判断树A中以R为跟节点的子树是不是包含和树B一样的结构(终止条件是到达树A(不含树B结构)或树B的叶节点(含有树B结构))
/*
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* pRoot1, TreeNode* pRoot2)
{
bool result = false;
if(pRoot1!=nullptr && pRoot2!=nullptr){
if(pRoot1->val == pRoot2->val)
//两个树的根节点相等,判断子树是否相等
result = DoesTree1HaveTree2(pRoot1,pRoot2);
if(!result)
//在左子树中查找
result = HasSubtree( pRoot1->left, pRoot2);
if(!result)
//在右子树中查找
result = HasSubtree( pRoot1->right, pRoot2);
}
return result;
}
bool DoesTree1HaveTree2(TreeNode* pRoot1, TreeNode* pRoot2){
//根节点相等才会进入到该函数
//给出终止条件
if(pRoot2==nullptr)
return true;
if(pRoot1==nullptr)
return false;
if(pRoot1->val != pRoot2->val)
return false;
//左右子树都相等,返回true
return DoesTree1HaveTree2(pRoot1->left,pRoot2->left) && DoesTree1HaveTree2(pRoot1->right,pRoot2->right);
}
};
编程时注意对nullptr的判断,以防代码报错。
2)利用好短路特性,完全不用那么多flag
class Solution {
bool isSubtree(TreeNode* pRootA, TreeNode* pRootB) {
if (pRootB == NULL) return true;
if (pRootA == NULL) return false;
if (pRootB->val == pRootA->val) {
return isSubtree(pRootA->left, pRootB->left)
&& isSubtree(pRootA->right, pRootB->right);
} else return false;
}
public:
bool HasSubtree(TreeNode* pRootA, TreeNode* pRootB)
{
if (pRootA == NULL || pRootB == NULL) return false;
return isSubtree(pRootA, pRootB) ||
HasSubtree(pRootA->left, pRootB) ||
HasSubtree(pRootA->right, pRootB);
}
};
3) KMP
左边数先序遍历是:1 2 4 5 3,右边是:1 2 3。
子树和子结构是两码事,子树的意思是给定一个节点就要遍历到它的所有叶节点为止,而子结构不需要,可以中途停止。子树能用序列化+KMP,子结构不能,因为子结构不管采用何种方式序列化,都不能保证在整棵树的序列化中连续
可以用KMP吧?都先序遍历,如果后者是前者的子结构,则后者的先序遍历序列一定是前者的先序遍历的子串(注意是子串,不是子序列),反之,如果不是子结构,B的固定先序有多种结构,但是一定不是前者的子串了。
学习KMP算法,怎样寻找子串
4)将树进行序列化的时候,空结点要用#号或其他符号填充,这样可以保证这个序列能唯一的表示一棵树,如后面有一个题目《树的序列化和反序列化》也是这样做的。
基础知识:
1)深度优先遍历(DFS)Depth First Search
和树的先序遍历比较类似。
2)广度优先搜索算法(Breadth First Search),又称为"宽度优先搜索"或"横向优先搜索",简称BFS。
https://www.cnblogs.com/skywang12345/p/3711483.html
3)KMP算法要解决的问题就是在字符串(也叫主串)中的模式(pattern)定位问题。说简单点就是我们平时常说的关键字搜索。模式串就是关键字(接下来称它为P),如果它在一个主串(接下来称为T)中出现,就返回它的具体位置,否则返回-1(常用手段)。
4)kmp时间复杂度是O(n + m), 递归查找O(n * m)
5)一种遍历可能有多种树,两种遍历才能确定一个树,