题目描述
输入两棵二叉树A,B,判断B是不是A的子结构。(ps:我们约定空树不是任意一个树的子结构)
思路
对于判断树的结构相关的,一般都是可以用递归的。既然要用递归,就要考虑递归的返回条件。
首先在第一次进入代码块的时候,根据题意,只要p2不存在就直接返回false,另一个,当p1不存在的时候也返回false。
但是,递归何时返回呢?当然是p2到底了,返回true,如果p2还没到底,p1已经到底了,当然是返回false.
这就带来了冲突,p2第一次进入为空就返回0,但是后续递归却要用到它是否为空。于是我们想到将这个递归放到另一个函数里面。
整体思路:
入口值相等,继续往下判断(这一部分在新的递归代码块实现);
入口值不相等,将p1的左子树和右子树分别与p2传进主代码块递归
实现
class Solution {
public:
bool dfs(TreeNode* p1,TreeNode* p2)
{
if (!p2) return 1;
if (!p1) return 0;
return (p1->val==p2->val)
&&dfs(p1->left,p2->left)
&&dfs(p1->right,p2->right);
//根结点相等时要左右子树全部满足才返回真
}
bool HasSubtree(TreeNode* pRoot1, TreeNode* pRoot2)
{
if (!pRoot1||!pRoot2) return 0;//第一次进入只要有空就返回false
return dfs(pRoot1,pRoot2)//根结点相等判断
||HasSubtree(pRoot1->left, pRoot2)//左子树自身递归
||HasSubtree(pRoot1->right, pRoot2);//右子树自身递归
//上面只要有一个满足就返回true
}
};
教训
在寻找递归返回条件时被上述的冲突给困住了。
对于这样的一个需求:
如果某种条件在第一次之后可以满足,但是第一次却不能满足,就要考虑新建一个递归函数
这里,p2==NULL时,返回false,如果这时候返回后面就无法进行了,但是后续却要依赖它为NULL来控制递归的返回。于是另外新建一个递归函数。