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

    文章

    2997

    浏览量

    115682
  • python
    +关注

    关注

    57

    文章

    4857

    浏览量

    89583

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

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

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

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    通过优化代码来提高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 886次阅读

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

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

    电路板上看到这样两个贴片,请教分别是什么元器件

    在一电路板上看到了以下两个元器件,但不知道是款元器件,麻烦大神给指导! 谢谢!
    发表于 02-25 21:22

    两个不同频率晶振靠的近会怎样

    晶振的振荡本质上是一种机械振动(在压电晶体层面)。当两个晶振靠得很近时,它们的机械振动可能会相互影响。一晶振的振动可能会通过电路板或者外壳等介质传递给另一晶振,从而改变另一晶振的
    的头像 发表于 01-20 13:55 2018次阅读
    <b class='flag-5'>两个</b>不同频率晶振靠的近会怎样

    求助,以下两个ADC转换的通道,分别是CC2541上的两个引脚啊?

    #define HAL_ADC_CHN_TEMP 0x0e /* Temperature sensor */ #define HAL_ADC_CHN_VDD3 0x0f /* VDD/3 */ 以上两个ADC转换的通道,分别是CC2541上的
    发表于 01-14 08:15

    如何把两个数据返回给调用函数

    函数的处理结果包含两个数据,如何把两个数据返回给调用函数? 第一种,把两个数据封装成一结构体,函数返回结构体。 调用函数的地方同样用结构体去接收函数的返回值。 第
    的头像 发表于 01-08 10:15 678次阅读

    嵌入式学习-飞凌嵌入式ElfBoard ELF 1板卡-初识设备之设备组成和结构

    适配不同的板卡。设备组成和结构及dts、dtb、dtsi设备Device Tree由一系列被命名的节点(node)和属性(property)组成,而节点本身可包含子
    发表于 01-08 08:32

    飞凌嵌入式ElfBoard ELF 1板卡-初识设备之设备组成和结构

    适配不同的板卡。设备组成和结构及dts、dtb、dtsi设备Device Tree由一系列被命名的节点(node)和属性(property)组成,而节点本身可包含子
    发表于 01-07 09:16

    西门子TIA Portal如何比较两个浮点数相等

    概述: 由于浮点数的定义规则,导致浮点数不能通过进制精确表示,所以在浮点数计算过程中,会出现两个值一样的浮点数进行比较相等计算时结果并不相等的情况。下面先设计一实例说明该问题,并给
    的头像 发表于 01-06 10:07 1161次阅读
    西门子TIA Portal如何<b class='flag-5'>比较</b><b class='flag-5'>两个</b>浮点数相等

    DAC8760的Iout和Vout都有两个TVS防护,这两个各是什么作用?

    1、DAC8760的Iout和Vout都有两个TVS防护,这两个各是什么作用? 2、如果我只希望DAC8760输出0-5V和4-20mA,输出电路的两个TVS都要加么?
    发表于 12-30 06:49

    通电后两个比较器LM331芯片发烫明显,为什么?

    通电后两个比较器LM331芯片发烫明显,然后U8的1脚及U9的3脚测量电压只有0.21V不符合理论计算的分压结果,I_bat的电压范围为在0-3.3V。请问是会是什么原因,谢谢。
    发表于 12-11 08:31