26 树的子结构(第3章 高质量的代码-代码的鲁棒性)
作者:互联网
题目描述:
输入两棵二叉树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)一种遍历可能有多种树,两种遍历才能确定一个树,
标签:return,代码,pRoot2,子结构,pRoot1,鲁棒性,TreeNode,pRootB 来源: https://www.cnblogs.com/GuoXinxin/p/10449529.html