牛客网剑指offer第17题——树的子结构

题目:

输入两棵二叉树A,B,判断B是不是A的子结构。(ps:我们约定空树不是任意一个树的子结构)

拿到这个题目,我们应该定义什么情况下是子结构:

当B的头节点等于A的头节点,并且左右子树的头节点也相等,则返回true,否则我们在A的左子树或者A的右子树中继续判断:

看下面代码:

bool HasSubtree(TreeNode* pRoot1, TreeNode* pRoot2)
    {
        if(pRoot1 == nullptr || pRoot2 == nullptr) return false;//边界处理
        if(pRoot1->val == pRoot2->val && isequal(pRoot1,pRoot2)) return true;
        return HasSubtree(pRoot1->left,pRoot2) || HasSubtree(pRoot1->right,pRoot2);
    }

显然,第一行代码用于边界判断,第二行代码,就是如果头节点相等,且头节点下的子树节点也相等,那么是子结构

第三行代码就是在A的左子树或者A的右子数中寻找。

显然,仅仅有一个递归结构式不行的,还需要我们判断子树节点相等这一条件,显然这也是一个递归的过程,因为子树也有子树,见下面代码:

1   bool isequal(TreeNode* p1,TreeNode* p2)//完成对子树结构的判断
2     {
3         if(p2 == nullptr) return true;
4         if(p1 == nullptr) return false;
5         if(p1->val != p2->val) return false;
6         return isequal(p1->left,p2->left)&& isequal(p1->right,p2->right);
7     }

如果我们抛开,1,2行代码,上述显然是对子树判断的标准递归。若子树头节点不相等,则返回false。若相等,则要求左边和左边相等,右边和右边相等。

当然了,1,2行的边界很重要:第一行的边界表明了子树B到了末尾了,此时自然返回true(注意区别其与上一段代码的边界的区别),第二行代码表明了,p2没有到末尾,反而父树到了末尾,此时必然是不是子结构。

posted @ 2020-04-04 19:00  少年π  阅读(221)  评论(0编辑  收藏  举报