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
    +关注

    关注

    19

    文章

    2957

    浏览量

    104535
  • python
    +关注

    关注

    55

    文章

    4779

    浏览量

    84440

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

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

收藏 人收藏

    评论

    相关推荐

    什么是默克尔(Merkle Tree)?如何计算默克尔根?

    01 默克尔的概念 默克尔(Merkle Tree)是一种特殊的二叉树,它的每个节点都存储了一数据块的哈希值。哈希值是一种可以将任意长
    的头像 发表于 09-30 18:22 587次阅读
    什么是默克尔<b class='flag-5'>树</b>(Merkle Tree)?如何计算默克尔根?

    两个极管反向串联是什么元件

    两个极管反向串联是一种常见的电路元件,通常被称为双向极管或双向稳压极管。这种元件具有独特的电气特性,可以在正向和反向电压下工作,广泛应用于各种电子电路中。 一、双向
    的头像 发表于 08-16 16:05 2379次阅读

    极管的伏安特性分为两个部分?

    极管是一种半导体器件,具有单向导电性。其伏安特性是描述极管在不同电压下电流变化的曲线。极管的伏安特性可以分为两个部分:正向特性和反向特性。 正向特性 正向特性是指
    的头像 发表于 08-16 11:16 639次阅读

    触发器的两个稳定状态分别是什么

    触发器作为数字电路中的基本逻辑单元,具有两个稳定状态,这两个状态通常用于表示进制数码中的0和1。
    的头像 发表于 08-12 11:01 596次阅读

    使用比较器TLV7041判断两个信号的大小,但输出未按预期进行是怎么回事?

    我现在需要使用比较判断两个信号的大小,但输出未按预期进行(不能比较者大小)。如下图,U17是比较
    发表于 08-12 08:20

    节点电压法流入节点电流怎么判断正负

    的电压。在分析过程中,我们需要判断流入节点的电流的正负。 节点电压法概述 在节点电压法中,我们首先选择一参考
    的头像 发表于 08-06 17:24 1609次阅读

    运放做比较两个输入相等怎么办

    比较器是运放的一种常见应用,主要用于比较两个模拟信号的大小。 当运放用作比较器时,其两个输入端分别为非反向输入端(+)和反向输入端(-)。
    的头像 发表于 07-10 10:34 813次阅读

    交流元继电器有两个线圈

    交流元继电器是一种常见的电气元件,广泛应用于各种电气控制系统中。它主要由两个线圈组成,这两个线圈分别是线圈1和线圈2。下面我们将详细介绍这两个线圈的特点、工作原理以及在实际应用中的注
    的头像 发表于 06-29 09:43 553次阅读

    对称短路有哪些 对称短路的形式有四种

    对称短路有哪些 对称短路的形式有四种  对称短路是指电路中的两个电路元件或导线之间有相同的电位差,从而形成电流的直接流动。
    的头像 发表于 02-18 10:17 2228次阅读

    Psoc4 4247LQI483如何判断产生的中断是由两个比较器中的哪一输出的上升沿触发的呢?

    LPcomparator的中断使能时,提示我们使用global signal reference并且选择LPCompInt。那么,我们如何判断这个产生的中断是由两个比较器中的哪一输出
    发表于 02-18 08:26

    ADuC824正弦波转方波时频带要比较宽时怎么办?

    低频时转换来的方波的波形单片机识别不了还是怎么的。有谁遇到过这种问题吗??有没有AD芯片低功耗频带快的比较器啊??我可以在比较器的输出端加两个对接的稳压管来时其输出的方波更好吗???
    发表于 01-15 06:42

    对称电源平衡指示器电路原理图

    电源平衡指示器显示对称电源是否真正对称。利用 LM339N 四路比较器的两个比较器对,我们可以制作这样的指示器。一对驱动红色警告 LED3,
    的头像 发表于 12-05 17:22 889次阅读
    <b class='flag-5'>对称</b>电源平衡指示器电路原理图

    两个硬盘2系统开机切换

    切换两个硬盘上的系统是一种常见的行为,可以让用户在不同的操作系统之间进行切换,以满足不同的需求。在本文中,我们将详细介绍如何配置和使用两个硬盘上的系统进行切换。本文将分为以下几个部分进行讨论:硬件
    的头像 发表于 11-28 15:08 7367次阅读

    堆的实现思路

    什么是堆? 堆是一种 基于树结构的数据结构,它是一棵二叉树 ,具有以下两个特点: 堆是一完全二叉树,即除了最后一层,其他层都是满的,最后一层从左到右填满。 堆中每个
    的头像 发表于 11-24 16:02 393次阅读
    堆的实现思路

    二叉树的定义

    型结构 是一类重要的 非线性数据结构 ,其中以二叉树最为常用,直观来看,是以分支关系定义的层次结构。型结构在客观世界中广泛存在,比
    的头像 发表于 11-24 15:57 1274次阅读
    <b class='flag-5'>树</b>与<b class='flag-5'>二叉树</b>的定义