题目描述
输入两棵二叉树A,B,判断B是不是A的子结构。(ps:我们约定空树不是任意一个树的子结构)
/* struct TreeNode { int val; struct TreeNode *left; struct TreeNode *right; TreeNode(int x) : val(x), left(NULL), right(NULL) { } };*/ class Solution { bool isSubtree(TreeNode *pRootA,TreeNode *pRootB) { if(pRootB == NULL) return true; if(pRootA == NULL) return false; if(pRootA->val == pRootB->val) { return isSubtree(pRootA->left,pRootB->left) && isSubtree(pRootA->right,pRootB->right); } else return false; } public: bool HasSubtree(TreeNode* pRoot1, TreeNode* pRoot2) { if(pRoot1 == NULL || pRoot2 == NULL) return false; return isSubtree(pRoot1,pRoot2)||isSubtree(pRoot1->left,pRoot2)||isSubtree(pRoot1->right,pRoot2); } };
本题中HasSubtree函数是程序入口,题目中说了空树不是任意一个树的子结构;isSubtree中RootB为空表示的是B树遍历结束了。
思考: 1.首先需要递归pRoot1树,找到与pRoot2根一样的节点,这需要一个遍历 2.找到相同的根节点后,要判断是否子树,仍需要一个一个遍历对比 树的遍历我们一般就用递归来做,那么根据分析需要两个递归函数如下: bool IsSubtree(TreeNode*p1, TreeNode *p2) { if (!p2) //此处为p2 == null 是匹配完成的条件 //最开始p2肯定不为NULL,这是在主程序HasSubtree中判断过的。 //递归中,如果p2为空了,则表示上一层的递归中的p2已经匹配完了 return true; if (!p1) return false; if (p1->val != p2->val) return false; return IsSubtree(p1->left, p2->left) && IsSubtree(p1->right, p2->right); } bool HasSubtree(TreeNode *pRoot1, TreeNode *pRoot2) { if(pRoot2 == nullptr) return false;//题目要求,空树不是任何树的子结构 if(pRoot1 == nullptr) return false; //显然 //return IsSubtree(pRoot1, pRoot2)||HasSubtree(pRoot1->left, pRoot2)|| HasSubtree(pRoot1->right, pRoot2); //为了思路清楚,分开谢了,可以利用||或运算直接return bool flag = IsSubtree(pRoot1, pRoot2);//看看B是不是以A的根为根的子结构 if (!flag)//递归A的左子树,看看做子树中有没有B子结构 flag = HasSubtree(pRoot1->left, pRoot2); if (!flag)//同上,递归A的右子树 flag = HasSubtree(pRoot1->right, pRoot2); return flag; } 其中需要注意的是: 1. 测试用例如果pRoot2为空的话,返回的false而不是我们认为的空树应该是所有树的子树 2. 再判断是否子树的过程中,应该先判断pRoot2是否为空,为空则表明子树的所有节点都比较完了,应该是子树返回True 3. 要养成一个习惯,对任何一个树节点进行访问时,一定要提前检测该节点是否为空