面试题18:树的子结构

     题目:输入两颗二叉树A和B ,判断B是不是A的子结构。

     想到关于二叉树的题目,基本可以按照递归的思路来做,很快写出以下代码:

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)
    {
        if(pRoot1==NULL)
            return false;
        else if(pRoot2==NULL||(pRoot2!=NULL&&(pRoot1->val==pRoot2->val&&pRoot2->left==NULL&&pRoot2->right==NULL)))    
            return true;                               //开始此处pRoot==NULL没写,直接段错误,想了一下,应该是没判断的话后面if中引用值就段错误
        if(pRoot2->val==pRoot1->val)                     //了
        {                                              //考虑节点相等,再考虑左右子树都相等就可
            return HasSubtree(pRoot1->left,pRoot2->left)&&HasSubtree(pRoot1->right,pRoot2->right);
        }
        else
        {                                              //该节点不行,分别访问左或者右子树,
            return HasSubtree(pRoot1->left,pRoot2)||HasSubtree(pRoot1->right,pRoot2);
        }
    }
};
      最后,好吧,测试用例A={8,8,7,9,2,#,#,#,#,4,7},B={8,9,2};没通过。

      gdb调试了一下,发现在寻找第一个根节点的8的时候,就跳进了if判断句中,导致我的程序输出的是false,可是按照测试用例,完全可以再向下遍历下,就可找到,但程序没有,所以出错。


      自己再修改了一段时间,还是有几个测试用例没通过。说明本身程序思路就有点问题。于是看了下书上的分析。

      分析如下,主要通过两步:

      一:寻找A树中节点的值与B树根节点值相同的点。

      二:再判断在A中以此为根节点的子结构是否和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!=NULL&&pRoot2!=NULL)
        {
            if(pRoot2->val==pRoot1->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==NULL)                           //此处如果是先判断pRoot1==NULL,return false,则不行,看来以后程序要从真的开始判断先。
            return true;
        if(pRoot1==NULL)
            return false;
       
       
        if(pRoot1->val!=pRoot2->val)
            return false;
        return DoesTree1HaveTree2(pRoot1->left,pRoot2->left)&&DoesTree1HaveTree2(pRoot1->right,pRoot2->right);
    }
};
      小结:

      在写程序的时候,考虑到遍历,但是没有想到先遍历树查找到与子树根节点相同的值,再进行判断,我就直接一上来就判断,然后返回了。对于开始没有,没有完全遍历完二叉树,就返回了结果。

       经常忘记判断节点是否为空。

      还有,对于返回bool类型,先设一个bool型的临时变量,再程序中间做改变是一个好的习惯,尤其是bool型可能要经常改变。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值