0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

这么简单的二叉树算法都不会?

算法与数据结构 来源:码农的荒岛求生 2023-08-29 11:19 次阅读

要求是这样的:给定两颗二叉树A和B,判断B是否是A的子树。

在下面这个例子中可以看到B是A的子树。

82e86654-40d6-11ee-a2ef-92fbcf53809c.png

想一想该怎样解决这个问题呢?

如果B是A的一颗子树,那么B一定和A的一个颗子树完全一样,因此我们可以实现一个函数isSame来判断两颗二叉树是否完全相同,这个函数非常容易实现:

bool isSame(TreeNode* a, TreeNode* b) {
    if (a == nullptr && b == nullptr) return true;
    else if (a == nullptr || b == nullptr) return false;
    else return a->val == b->val && isSame(a->left, b->left) && isSame(a->right, b->right);
}
只需要三行代码就能搞定,该函数非常简单:

如果二叉树a和b都为空,那么显然返回true

否则如果a为空或者b为空,那么这两棵树显然不相同,返回false

如果不满足条件1和2,那么如果a和b根节点的值相同并且其左右子树都一样,那么二叉树a和b是相同的二叉树,返回true

有了isSame函数剩下的就简单啦,我们只需要在遍历二叉树a时不断的调用isSame函数判断是否b是a的子树相同:

8302fab4-40d6-11ee-a2ef-92fbcf53809c.png

同样的,只需要三行代码就能搞定:

bool isSubtree(TreeNode* root, TreeNode* subRoot) {
    if (root == nullptr && subRoot == nullptr) return true;
    else if (root == nullptr || subRoot == nullptr) return false;
    else return isSame(root, subRoot) || isSubtree(root->left, subRoot) || isSubtree(root->right, subRoot);
}
代码非常简单,就是二叉树的普通遍历。

有的同学可能已经发现了,这种算法的实际上不太高效,原因就在于对于二叉树a上的每个节点我们都需要调用一遍isSame函数,如果二叉树a的节点数为M、二叉树b的节点数为N,那么该算法的时间复杂度为O(M*N)。

我们一定对二叉树a中的每个节点都调用一遍isSame函数吗?

实际上这并不是必须的。

要能想出更高效的算法,你需要理解编码的概念。

熟悉md5的同学都知道,我们可以对任何一个文件计算出md5值,md5就是一串数字,就好像指纹一样,只需要两个文件完全一样,那么这两个文件的md5就完全一样,因此我们可以通过比较md5来确认两个文件是否完全一样,在linux下用md5sum命令可以计算一个文件的md5值:
$ md5sum a.c
6004b6a21b274b405a2bd1f1c75a93c7  a.c
同样的,我们也可以对二叉树计算“md5”值。

怎么计算呢?

实际上非常简单。

我们只需要在二叉树的前序遍历过程中输出“遍历轨迹”,那么就能将一颗二叉树序列化成一个字符串

如果二叉树b是a的子树,那么必然二叉树b序列化的后的字符串是a序列化后的字符串的子串。

这样通过编码,我们将二叉树子树的判断问题转化为了字符串的子串匹配问题,而字符串匹配问题可以通过经典的KMP算法解决。

83219c08-40d6-11ee-a2ef-92fbcf53809c.png

将二叉树序列化为字符串的函数也很简单:
void serialize(TreeNode* root, string& str) {
    if (root == nullptr) {
        str = str + "#";
    } else {
        str = str  + "," + to_string(root->val);


        serialize(root->left, str);
        serialize(root->right, str);
    }
}
可以看到,该代码实际上还是二叉树的遍历。

既然我们可以将二叉树序列化了字符串,那么接下来就简单啦:
bool isSubtree(TreeNode* root, TreeNode* subRoot) {
    string a, b;
    serialize(root, a);
    serialize(subRoot, b);
    return a.find(b)!=string::npos;
}
将二叉树序列化为字符串后只需要判断字符串b是否是字符串a的子串即可。

从这个题目上我们可以看到信息编码的重要作用,这也是一种非常值得掌握的思想,有时对解决问题有四两拨千斤的效果






审核编辑:刘清

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 编码器
    +关注

    关注

    41

    文章

    3361

    浏览量

    131555
  • Linux系统
    +关注

    关注

    4

    文章

    567

    浏览量

    26920
  • 字符串
    +关注

    关注

    1

    文章

    552

    浏览量

    20130
  • 二叉树
    +关注

    关注

    0

    文章

    74

    浏览量

    12240

原文标题:面试官:这么简单的二叉树算法都不会?

文章出处:【微信号:TheAlgorithm,微信公众号:算法与数据结构】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    二叉树二叉树的性质(1)#数据结构

    数据函数二叉树
    未来加油dz
    发布于 :2023年09月05日 09:06:44

    二叉树二叉树的性质(2)#数据结构

    数据函数二叉树
    未来加油dz
    发布于 :2023年09月05日 09:08:32

    二叉树二叉树的性质(3)#数据结构

    数据函数二叉树
    未来加油dz
    发布于 :2023年09月05日 09:09:51

    计算机二叉树的问题

    各位大神,本人马上要考计算机级了,那个二叉树老是弄不明白,比如一个题目,一棵二叉树共有25个节点,其中五个叶子节点,则度为1的节点数为?
    发表于 09-04 09:45

    二叉树删除算法

    二叉树的删除操作主要是寻找替代点来进行替换操作。方法:先右转,再一直左转,直到左连接为空的那个点。然后,摘取出来,完成链接指向操作。public void deletmin(void){ root
    发表于 12-30 20:55

    二叉查找(GIF动图讲解)

    二叉查找(Binary Search Tree),也称二叉搜索,是指一棵空或者具有下列性质的二叉树
    发表于 07-29 15:24

    2016大疆笔试题与总结(编程类)

    总体来说,大疆的题目不算太难。尤其是编程题,思路很清晰,不涉及到太复杂的算法。只有第三题可能涉及到递归操作(软肋)。其中第题有关完全二叉树的操作,只需要知道完全二叉树的四个重要性质就
    发表于 11-21 15:28

    【案例分享】经典的压缩算法Huffman算法

    字符出现频率,Priority Queue,和二叉树来进行的一种压缩算法,这种二叉树又叫Huffman二叉树 —— 一种带权重的。从学校毕
    发表于 07-17 04:30

    用C语言构建一个二叉树失败

    ; ,tree.leftnode->data);这三个输出都是乱码,我不知道二叉树的建立过程中问题在哪里,我应该在每个节点都分配了内存,不过结果好像有问题}
    发表于 03-24 03:47

    什么是“红黑”看了就知道

    今天我们要说的红黑就是就是一棵非严格均衡的二叉树,均衡二叉树又是在二叉搜索的基础上增加了自动维持平衡的性质,插入、搜索、删除的效率都比较
    发表于 10-27 17:00

    Java编程求二叉树的镜像两种方法介绍

    给出一棵二叉树,求它的镜像,如下图:右边是二叉树是左边二叉树的镜像。仔细分析这两棵的特点,看看能不能总结出求镜像的步骤。这两棵的根节点相
    发表于 12-16 16:25

    二叉树算法在单总线技术中的应用

    介绍了单总线技术和二叉树算法。单总线技术可以将地址线、数据线和控制线合成一根线,并允许在这根线上挂接多个单总线器件。提出了用二叉树算法搜索单总线器件注册码,并
    发表于 03-16 09:38 20次下载

    基于二叉树分解的自适应防碰撞算法

    该文提出了一种基于二叉树分解的自适应防碰撞算法。新算法利用标签EPC 的唯一性,通过时隙分配估计标签的分布情况,对发生碰撞的时隙进行二叉树搜索,从而将一个庞大且复杂
    发表于 11-17 14:09 21次下载

    二叉树层次遍历算法的验证

    实现二叉树的层次遍历算法,并对用”A(B(D,E(H(J,K(L,M(,N))))),C(F,G(,I)))”创建的二叉树进行测试。
    发表于 11-28 01:05 1909次阅读
    <b class='flag-5'>二叉树</b>层次遍历<b class='flag-5'>算法</b>的验证

    二叉树的代码实现

    二叉树的主要操作有遍历,例如有先序遍历、中序遍历、后序遍历。在遍历之前,就是创建一棵二叉树,当然,还需要有删除二叉树算法
    的头像 发表于 01-18 10:41 907次阅读
    <b class='flag-5'>二叉树</b>的代码实现