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

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

3天内不再提示

判断对称二叉树要比较的是哪两个节点

算法与数据结构 来源:代码随想录 作者:程序员Carl 2022-07-06 16:26 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

101. 对称二叉树

给定一个二叉树,检查它是否是镜像对称的。

c54bc0e8-fd04-11ec-ba43-dac502259ad0.png

思路

首先想清楚,判断对称二叉树要比较的是哪两个节点,要比较的可不是左右节点!

对于二叉树是否对称,要比较的是根节点的左子树与右子树是不是相互翻转的,理解这一点就知道了其实我们要比较的是两个树(这两个树是根节点的左右子树),所以在递归遍历的过程中,也是要同时遍历两棵树。

那么如果比较呢?

比较的是两个子树的里侧和外侧的元素是否相等。如图所示:

c56013f4-fd04-11ec-ba43-dac502259ad0.png

那么遍历的顺序应该是什么样的呢?

本题遍历只能是“后序遍历”,因为我们要通过递归函数的返回值来判断两个子树的内侧节点和外侧节点是否相等。

正是因为要遍历两棵树而且要比较内侧和外侧节点,所以准确的来说是一个树的遍历顺序是左右中,一个树的遍历顺序是右左中。

但都可以理解算是后序遍历,尽管已经不是严格上在一个树上进行遍历的后序遍历了。

其实后序也可以理解为是一种回溯,当然这是题外话,讲回溯的时候会重点讲的。

说到这大家可能感觉我有点啰嗦,哪有这么多道理,上来就干就完事了。别急,我说的这些在下面的代码讲解中都有身影。

那么我们先来看看递归法的代码应该怎么写。

递归法

递归三部曲

确定递归函数的参数和返回值

因为我们要比较的是根节点的两个子树是否是相互翻转的,进而判断这个树是不是对称树,所以要比较的是两个树,参数自然也是左子树节点和右子树节点。

返回值自然是bool类型。

代码如下:

poYBAGLFR4yAPVqWAAAQuPTXo1A904.jpg

确定终止条件

要比较两个节点数值相不相同,首先要把两个节点为空的情况弄清楚!否则后面比较数值的时候就会操作空指针了。

节点为空的情况有:(注意我们比较的其实不是左孩子和右孩子,所以如下我称之为左节点右节点)

左节点为空,右节点不为空,不对称,return false

左不为空,右为空,不对称 return false

左右都为空,对称,返回true

此时已经排除掉了节点为空的情况,那么剩下的就是左右节点不为空:

左右都不为空,比较节点数值,不相同就return false

此时左右节点不为空,且数值也不相同的情况我们也处理了。

代码如下:

pYYBAGLFR6aAY2QmAABITjMqXUc205.jpg

注意上面最后一种情况,我没有使用else,而是elseif, 因为我们把以上情况都排除之后,剩下的就是 左右节点都不为空,且数值相同的情况。

确定单层递归的逻辑

此时才进入单层递归的逻辑,单层递归的逻辑就是处理 右节点都不为空,且数值相同的情况。

比较二叉树外侧是否对称:传入的是左节点的左孩子,右节点的右孩子。

比较内测是否对称,传入左节点的右孩子,右节点的左孩子。

如果左右都对称就返回true ,有一侧不对称就返回false 。

代码如下:

poYBAGLFR8GAek6NAABGcSkJYew381.jpg

如上代码中,我们可以看出使用的遍历方式,左子树左右中,右子树右左中,所以我把这个遍历顺序也称之为“后序遍历”(尽管不是严格的后序遍历)。

最后递归的C++整体代码如下:

poYBAGLFR9-AKoDSAADhGvnLjmI811.jpg

我给出的代码并不简洁,但是把每一步判断的逻辑都清楚的描绘出来了。

如果上来就看网上各种简洁的代码,看起来真的很简单,但是很多逻辑都掩盖掉了,而题解可能也没有把掩盖掉的逻辑说清楚。

盲目的照着抄,结果就是:发现这是一道“简单题”,稀里糊涂的就过了,但是真正的每一步判断逻辑未必想到清楚。

当然我可以把如上代码整理如下:

pYYBAGLFR_WAakX3AACMdaxuhp0814.jpg

这个代码就很简洁了,但隐藏了很多逻辑,条理不清晰,而且递归三部曲,在这里完全体现不出来。

所以建议大家做题的时候,一定要想清楚逻辑,每一步做什么。把道题目所有情况想到位,相应的代码写出来之后,再去追求简洁代码的效果。

迭代法

这道题目我们也可以使用迭代法,但要注意,这里的迭代法可不是前中后序的迭代写法,因为本题的本质是判断两个树是否是相互翻转的,其实已经不是所谓二叉树遍历的前中后序的关系了。

这里我们可以使用队列来比较两个树(根节点的左右子树)是否相互翻转,(注意这不是层序遍历)

使用队列

通过队列来判断根节点的左子树和右子树的内侧和外侧是否相等,如动画所示:

c575382e-fd04-11ec-ba43-dac502259ad0.gif

如下的条件判断和递归的逻辑是一样的。

代码如下:

poYBAGLFSBGAefZLAADwW9iQ3gw401.jpg

使用栈

细心的话,其实可以发现,这个迭代法,其实是把左右两个子树要比较的元素顺序放进一个容器,然后成对成对的取出来进行比较,那么其实使用栈也是可以的。

只要把队列原封不动的改成栈就可以了,我下面也给出了代码。

poYBAGLFSCiAYppNAACr8ADruEI559.jpg

总结

这次我们又深度剖析了一道二叉树的“简单题”,大家会发现,真正的把题目搞清楚其实并不简单,leetcode上accept了和真正掌握了还是有距离的。

我们介绍了递归法和迭代法,递归依然通过递归三部曲来解决了这道题目,如果只看精简的代码根本看不出来递归三部曲是如果解题的。

在迭代法中我们使用了队列,需要注意的是这不是层序遍历,而且仅仅通过一个容器来成对的存放我们要比较的元素,知道这一本质之后就发现,用队列,用栈,甚至用数组,都是可以的。

如果已经做过这道题目的同学,读完文章可以再去看看这道题目,思考一下,会有不一样的发现!

相关题目推荐

100.相同的树

572.另一个树的子树

其他语言版本

Java

pYYBAGLFSF2ADY9uAACr4DprcZA332.jpg

poYBAGLFSG6AKXUhAAEOFGGfMWU626.jpg

poYBAGLFSHaAackKAAD6VGhZVno319.jpg

Python

递归法:

poYBAGLFSIyASH4MAADTVj4n-so737.jpg

迭代法:使用队列

poYBAGLFSKCAcVZxAADvrTwwIis108.jpg

迭代法:使用栈

poYBAGLFSLaAWPsjAACc4bGIAhg462.jpg





审核编辑:刘清

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

    关注

    20

    文章

    3015

    浏览量

    117024
  • python
    +关注

    关注

    59

    文章

    4892

    浏览量

    90417

原文标题:判断二叉树是否对称

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

收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    ADSP21565 dsp如何控制两个节点,还可以用a2b_stack嘛?

    ADSP21565 dsp如何控制两个节点(AD2428),还可以用a2b_stack嘛?
    发表于 05-13 07:40

    虹科分享 | 如何精准判断LIN总线从节点是否在线?

    今天给大家分享一比较实用的方法:如何精准地判断LIN总线上的从节点是否与主节点通讯。也许这时你会觉得奇怪:“我直接用诊断电脑读取故障码不就
    的头像 发表于 04-16 11:40 190次阅读
    虹科分享 | 如何精准<b class='flag-5'>判断</b>LIN总线从<b class='flag-5'>节点</b>是否在线?

    FreeRTOS_SMP_Example_S32K358_2xCores示例配置并实现了一SMP项目,两个核心的中断频率比较高时报故障,怎么解决?

    我参考FreeRTOS_SMP_Example_S32K358_2xCores示例配置并实现了一 SMP 项目。RTD6.0.0但是,当我的两个核心的中断频率比较高时,会出现种故障
    发表于 03-30 08:23

    深入理解设备chosen节点:固件与内核的“配置桥梁”

    在嵌入式 Linux 开发中,设备(Device Tree)是连接硬件与内核的关键纽带。但有一节点很特殊 —— 它不描述任何硬件模块,却直接决定内核能否正常启动,这就是chosen节点
    的头像 发表于 02-09 16:36 369次阅读
    深入理解设备<b class='flag-5'>树</b>chosen<b class='flag-5'>节点</b>:固件与内核的“配置桥梁”

    两个RS485-Modbus主站如何通讯

    本产品能很好解决Master-1主站向模块写入数据,Master-2主站读取数据;Master-2主站向模块写入数据,Master-1主站读取数据。由此解决两个主站之间的互相读通信难题。
    发表于 02-08 15:32 1次下载

    曙光存储连续斩获两个行业奖项

    近期,曙光存储连续斩获两个行业奖项,自研技术产品在国产突破、AI行业应用等方面的成果获得广泛关注。
    的头像 发表于 01-15 16:28 2790次阅读

    一文读懂:直线模组两个滑块距离能否调节?

    关键问题:直线模组中的两个滑块距离可以调节吗?答案并非绝对,而是要根据直线模组的具体类型、结构设计来综合判断,不同类型的直线模组在滑块距离调节上有着截然不同的特性。​飞
    的头像 发表于 12-29 15:47 530次阅读
    一文读懂:直线模组<b class='flag-5'>两个</b>滑块距离能否调节?

    深入解析SMFA非对称系列表面贴装TVS极管

    深入解析SMFA非对称系列表面贴装TVS极管 在电子设备的设计中,保护关键元件免受电压瞬变和浪涌的影响至关重要。TVS(瞬态电压抑制)极管作为一种常用的保护器件,能够在瞬间吸收大量的能量,将电压
    的头像 发表于 12-15 16:40 574次阅读

    通过优化代码来提高MCU运行效率

    选择时间复杂度低的算法。 根据访问模式选择数据结构。频繁查找用哈希表,有序数据用二叉树等。 查表法:对于复杂的数学计算(如sin, log),或者协议解析,预先计算好结果存于数组中,用空间换时间
    发表于 11-12 08:21

    蜂鸟E203内核中断管理模块sirv_plic_man代码分析

    。 上面的代码生成一二叉树结构来比较和选择具有最大优先级的挂起中断源及其ID。树状结构由级联比较器组成,每一层的比较器数量是前
    发表于 10-23 06:05

    两个模拟SPI,只有第二个正常,为什么?

    两个模拟SPI,一用于VS1003,另一用于SPI模式的SD卡。只有第二个SPI可以正常使用, static struct stm32_soft_spi_config
    发表于 09-29 07:19

    硬件SPI两个CS操作两个norflash,怎么互斥操作两个norflash?

    硬件SPI两个CS操作两个norflash,怎么互斥操作两个norflash,有一norflash被模拟成U盘,会在中断中操作spi。
    发表于 09-26 06:18

    基本半导体连获两个行业奖项

    近日,基本半导体凭借在碳化硅模块领域的突出表现,连获“国产SiC模块TOP企业奖”和“年度优秀功率器件产品奖”两个行业奖项。
    的头像 发表于 09-05 16:31 1287次阅读

    图中两个按键开关是两个干簧管,为什么不直接对GND设计来检测这个干簧管通断呢?

    图中两个按键开关是两个干簧管,为什么不直接对GND设计来检测这个干簧管通断呢? 这样设计的原理是什么?
    发表于 06-17 06:30

    看到STM8L152用两个IO用两个或非门检测两个通断,是什么原理呢?

    图中两个按键开关是两个干簧管,为什么不直接对GND设计来检测这个干簧管通断呢? 这样设计的原理是什么?
    发表于 06-12 06:25