首页 > 代码库 > 树的子结构

树的子结构

题目描述

输入两棵二叉树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. 要养成一个习惯,对任何一个树节点进行访问时,一定要提前检测该节点是否为空

  

 

树的子结构