树的结构比链表多了更多的指针操作,必须时刻注意代码鲁棒性,也就是注意是否对空指针进行操作了。
这道题用递归解决,如果p1或p2有一个为空,直接返回false。不然就对p1这棵树进行dfs(前序遍历),找是否有结点值和p2的结点值相等。如果有一个结点为空,直接返回false。如果找到某个结点和p2相等,就对这个结点进行dfs,判断这个结点下面是否有和p2一样的结构,因为是递归判断,所以有递归边界和递归式,递归边界就是如果p2为空结点,就返回true;如果p1为空结点就返回false,因为既然进行了这步判断,证明p2不为空,但是p1为空,所以false。**(搞清楚这里的p1p2和上面的p1p2不一样)**如果两个结点值不相等也是false。最后是递归式,递归判断p1的左子结点和p2的左子结点 && p1的右子结点和p2的右子结点。回到上一个函数,如果当前结点作为子结构的根结点不对,就去左子树找,左子树也找不到的话就去右子树找。最后返回结果。如果找到了一个符合结果的结点,一定会一直返回true的
/*
struct TreeNode {
int val;
struct TreeNode *left;
struct TreeNode *right;
TreeNode(int x) :
val(x), left(NULL), right(NULL) {
}
};*/
class Solution {
public:
bool hasCommon(TreeNode* pRoot1, TreeNode* pRoot2){
bool result = false;
if(pRoot1 != NULL && pRoot2 != NULL){
if(pRoot1->val == pRoot2->val){
result = hasSubStruct(pRoot1,pRoot2);
}
if(!result){
result = hasCommon(pRoot1->left,pRoot2);
}
if(!result){
result = hasCommon(pRoot1->right,pRoot2);
}
}
return result;
}
bool hasSubStruct(TreeNode* pRoot1, TreeNode* pRoot2){
if(pRoot2 == NULL){//递归结束条件
return true;
}
if(pRoot1 == NULL){
return false;
}
if(pRoot1->val != pRoot2->val){//判断不相等条件
return false;
}
return hasSubStruct(pRoot1->left,pRoot2->left) && hasSubStruct(pRoot1->right,pRoot2->right);
}
bool HasSubtree(TreeNode* pRoot1, TreeNode* pRoot2)
{
//空树不是任意一个树的子结构,指针=检查鲁棒性
if(pRoot1 == NULL || pRoot2 == NULL){
return false;
}
//先dfs(先序)在root1里面找,找到val和root2一样的,就检查这个结点
//检查这个结点也就是判断它和root2是否相同
return hasCommon(pRoot1,pRoot2);
}
};