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

news2024/11/29 12:38:01

今天我们来看一个有趣的算法题,也是一道高频面试题。这个题目是leetcode的第572题,要求是这样的:给定两颗二叉树A和B,判断B是否是A的子树。在下面这个例子中可以看到B是A的子树。

想一想该怎样解决这个问题呢?如果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);
}

 

只需要三行代码就能搞定,该函数非常简单:

  1. 如果二叉树a和b都为空,那么显然返回true
  2. 否则如果a为空或者b为空,那么这两棵树显然不相同,返回false
  3. 如果不满足条件1和2,那么如果a和b根节点的值相同并且其左右子树都一样,那么二叉树a和b是相同的二叉树,返回true

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

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

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

 

  资料直通车:Linux内核源码技术学习路线+视频教程内核源码

学习直通车:Linux内核源码内存调优文件系统进程管理设备驱动/网络协议栈

同样的,我们也可以对二叉树计算“md5”值。怎么计算呢?实际上非常简单。我们只需要在二叉树的前序遍历过程中输出“遍历轨迹”,那么就能将一颗二叉树序列化成一个字符串。如果二叉树b是a的子树,那么必然二叉树b序列化的后的字符串是a序列化后的字符串的子串。这样通过编码,我们将二叉树子树的判断问题转化为了字符串的子串匹配问题,而字符串匹配问题可以通过经典的KMP算法解决。

将二叉树序列化为字符串的函数也很简单:

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的子串即可。从这个题目上我们可以看到信息编码的重要作用,这也是一种非常值得掌握的思想,有时对解决问题有四两拨千斤的效果

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/576397.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Python丨tkinter开发常用的29种功能用法(建议码住)

在Python软件开发中,tkinter中command功能的作用是为按钮、菜单等组件绑定回调函数,用户操作该组件时会触发相应的函数执行。 本文涵盖了各种组件和功能: 1、为Button组件(按钮)绑定回调函数 import tkinter as tk …

模拟量偏差报警功能块(SCL代码)

工业模拟量采集的相关基础知识,可以查看专栏的系列文章,这里不再赘述,常用链接如下: PLC模拟量采集算法数学基础(线性传感器)_plc傳感器數據轉化_RXXW_Dor的博客-CSDN博客模拟量采集库如何设计,具体算法代码请参看我的另一篇博文:PLC模拟量输入 模拟量转换FC:S_ITR_R…

栈和队列(详解)

🍕博客主页:️自信不孤单 🍬文章专栏:数据结构与算法 🍚代码仓库:破浪晓梦 🍭欢迎关注:欢迎大家点赞收藏关注 文章目录 🍓栈1. 栈的概念及结构2. 栈的实现2.1 初始化栈2.…

MySQL运维篇(三)

五.读写分离 5.1 介绍 读写分离,简单地说是把对数据库的读和写操作分开,以对应不同的数据库服务器。主数据库提供写操作,从数据库提供读操作,这样能有效地减轻单台数据库的压力。 通过MyCat即可轻易实现上述功能,不仅可以支持MySQL&#x…

【论文总结】Composition Kills: A Case Study of Email Sender Authentication

构成杀伤力: 电子邮件发送者认证的案例研究 摘要 基于组件的软件设计是构建现代软件系统的一种主要工程方法。然而,由于不同组件之间对信息的解释可能不一致,这种编程范式产生了安全问题。在本文中,我们利用这种不一致来识别电子…

双列集合 JAVA

双列集合 一次需要添加一对数据,分别为键和值键不可以重复,值可以重复键和值是一一对应的,每一个键只可以找到自己对应的值键值对在java中也叫做Entry对象 #mermaid-svg-zKLj0vUbRaN9zlse {font-family:"trebuchet ms",verdana,ar…

SpringBoot2-基础入门(二)

SpringBoot2 - 基础入门(二) 了解自动装配原理 文章目录 SpringBoot2 - 基础入门(二)了解自动装配原理一、依赖管理1.1 父项目做依赖管理1.2 starer场景启动器 2、自动配置2.1 自动配置依赖2.2 组件扫描 3、配置文件3.1 各种配置…

【软件测试知识】

目录 软件测试软件测试模型瀑布模型V 模型W 模型敏捷开发模型 软件开发流程软件测试方法白盒测试黑盒测试 软件测试 软件测试模型 说到开发模型,从软件发展来看,比较典型的有瀑布模型,V 模型和 W 模型以及 敏捷开发模型。并不是说开发模型的…

【论坛java项目】第二章 Spring Boot实践,开发社区登录模块:发送邮件、开发注册功能、会话管理、生成验证码、开发登录、退出功能、

😀如果对你有帮助的话😊 🌺为博主点个赞吧 👍 👍点赞是对博主最大的鼓励😋 💓爱心发射~💓 目录 一、发送邮件1、启用客户端SMTP服务2、导入jar包3、邮箱参数配置MailClientdemo.html…

第13届蓝桥杯Scratch省赛真题集锦

编程题 第 1 题 问答题 报数游戏 题目说明 背景信息: 5个男生和3个女生,8个人围成一个圆圈,给定一个数字n (2 小于等于n 小于等于5)。从第一个开始依次报数,当报数为n时,这个人离开圆圈。然后下一个从1开始报数,再次报…

MySQL---使用索引优化、大批量插入数据优化

1. 使用索引优化 索引是数据库优化最常用也是最重要的手段之一, 通过索引通常可以帮助用户解决大多数的MySQL 的性能优化问题: create table tb_seller (sellerid varchar (100),name varchar (100),nickname varchar (50),password varchar (60),status varchar…

高级Java多线程面试题及回答

高级Java多线程面试题及回答 1)现在有T1、T2、T3三个线程,你怎样保证T2在T1执行完后执行,T3在T2执行完后执行? 这个线程问题通常会在第一轮或电话面试阶段被问到,目的是检测你对”join”方法是否熟悉。这个多线程问题比较简单,可…

网络安全的红利还能吃几年?

在我看来这是一个伪命题,因为网络安全的核心和本质是持续对抗,只要威胁持续存在,网络安全的红利就会持续存在! 对于网络安全新入行的同学们来说,这是一个最坏的时代,因为你只能自己搭环境才能重现那些大牛们…

网络编程 lesson5 IO多路复用

select 当需要在一个或多个文件描述符上等待事件发生时,可以使用select函数。 select函数是一个阻塞调用,它会一直等待,直到指定的文件描述符上有事件发生或超时。 select函数详解 int select(int nfds, fd_set *readfds, fd_set *writefd…

初识SPDK,从SPDK的软件架构到使用实操

相信很多做存储的同学都听说过SPDK,它是Intel开发的一套开源存储栈。SPDK的全称为存储高性能开发包(Storage Performance Development Kit),从名称可以看出SPDK其实就是一个第三方的程序库。但是这个程序库却是非常强大的,下图是SPDK的软件模块图,从该图可以看出,几乎囊…

Linux---用户管理命令(useradd、userdel、usermod、passwd、id)

1. 用户与用户组 Linux系统是一个多用户多任务的分时操作系统,任何一个要使用系统资源的用户,都必须首先向 系统管理员申请一个账号,然后以这个账号的身份进入系统。 Linux系统中可以: 配置多个用户、配置多个用户组、用户可以…

什么?电路板上还要喷漆?

什么是三防漆? 三防漆是一种特殊配方的涂料,用于保护线路板及其相关设备免受环境的侵蚀。三防漆具有良好的耐高低温性能;其固化后成一层透明保护膜,具有优越的绝缘、防潮、防漏电、防震、防尘、防腐蚀、防老化、耐电晕等性能。 在…

MIT6824——lab4(实现一个分片kv存储)的一些实现,问题,和思考

Part A 分片控制器 1. 整体思路 和lab3A一样,shardctler也是一个服务,由客户端调用。这个服务建立在raft集群上,保证容错。 shardctler也应该保证线性一致性和重复请求的问题,因此也需要记录clientid和messageid。 shardctler保…

BFT 最前线 | 张一鸣成立个人基金;马斯克:AI是双刃剑;阿里首席安全科学家离职;卡内基梅隆究团队:解决农业虫卵问题的机器人

文 | BFT机器人 名人动态 CELEBRITY NEWS 01 字节跳动创始人张一鸣 在香港成立个人投资基金 在卸任CEO两年后,字节跳动创始人张一鸣在香港成立了一家个人投资基金。香港公司注册处网站显示,该基金名为Cool River Venture,性质是私人股份有限…

doris索引

目前 Doris 主要支持两类索引: - 内建的智能索引:包括前缀索引和 ZoneMap 索引。 - 用户创建的二级索引:包括 Bloom Filter 索引 和 Bitmap倒排索引。其中 ZoneMap 索引是在列存格式上,对每一列自动维护的索引信息,包…