当前位置: 首页 > news >正文

【LeetCode刷题日记】面试官最爱的二叉树题:对称二叉树——递归+BFS双解法一网打尽

🔥个人主页:北极的代码(欢迎来访)
🎬作者简介:java后端学习者
❄️个人专栏:苍穹外卖日记,SSM框架深入,JavaWeb
命运的结局尽可永在,不屈的挑战却不可须臾或缺!

摘要:

本文探讨了判断二叉树是否对称的两种解法。递归法通过比较左右子树是否互为镜像,满足三个条件:节点值相等、左子树与右子树镜像、右子树与左子树镜像。迭代法使用队列进行广度优先搜索,成对比较节点并检查对称性。两种方法均需处理空节点情况,确保结构对称性和数值一致性。代码示例展示了递归和迭代的具体实现,通过逐层比较节点值及其子节点关系来判断对称性。该问题考察了对二叉树遍历和镜像概念的理解。

题目背景:101.对称二叉树

给你一个二叉树的根节点root, 检查它是否轴对称。

示例 1:

输入:root = [1,2,2,3,4,4,3]输出:true

示例 2:

输入:root = [1,2,2,null,3,null,3]输出:false

提示:

  • 树中节点数目在范围[1, 1000]
  • -100 <= Node.val <= 100

进阶:你可以运用递归和迭代两种方法解决这个问题吗?

题目分析:

其实我们在LeetCode刷题的时候,不能仅仅是看题目的难度,如果看到标的是简单,可能会产生忽视心理,同时如果没思路,也很会影响心态,我们要保持平常心,认真的对待每一题,往往有的简单题也蕴含着很深刻的知识。

首先我们来看这个题目。要我们来判断这个二叉树是否对称,我们就要想,怎么判断它是否对称呢,我们观察一下题目中给出的示例,对称其实就是左右是一个镜像,左子树等于右子树,简单的说我们只需要完成下列判断:

判断二叉树是否对称 = 判断左右子树是否互为镜像

两个树互为镜像的条件是:

  1. 两个根节点的值相同

  2. 树1的左子树 与 树2的右子树 互为镜像

  3. 树1的右子树 与 树2的左子树 互为镜像

1 / \ 2 2 / \ / \ 3 4 4 3 判断流程: 比较节点(2, 2):值相等 ✓ ├── 比较(2的左=3, 2的右=3):3==3 ✓ │ ├── 比较(3的左=null, 3的右=null):null==null ✓ │ └── 比较(3的右=null, 3的左=null):null==null ✓ └── 比较(2的右=4, 2的左=4):4==4 ✓ ├── 比较(4的左=null, 4的右=null):null==null ✓ └── 比较(4的右=null, 4的左=null):null==null ✓

我们下面用两种方法来解决

递归法(DFS):

首先我们照旧判断二叉树的根节点是否为null,如果为null直接返回。

然后我们判断是否为镜像:

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

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

返回值自然是bool类型。

  1. 确定终止条件

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

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

  • 左节点为空,右节点不为空,不对称,return false
  • 左不为空,右为空,不对称 return false
  • 左右都为空,对称,返回true

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

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

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

  1. 确定单层递归的逻辑

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

  • 比较二叉树外侧是否对称:传入的是左节点的左孩子,右节点的右孩子。
  • 比较内侧是否对称,传入左节点的右孩子,右节点的左孩子。
  • 如果左右都对称就返回true ,有一侧不对称就返回false 。

java

return (t1.val == t2.val) // 条件1:值相等 && isMirror(t1.left, t2.right) // 条件2:左的左 与 右的右 互为镜像 && isMirror(t1.right, t2.left); // 条件3:左的右 与 右的左 互为镜像

这三个条件用&&连接,缺一不可

代码行判断什么为什么重要
if (t1 == null && t2 == null) return true;两个都是空节点基础情况,递归的终点
if (t1 == null || t2 == null) return false;其中一个为空结构不对称(一个有空,另一个没有)
(t1.val == t2.val)两个节点的值相等数值不对称也不行
isMirror(t1.left, t2.right)外层与内层对称镜像的核心要求
isMirror(t1.right, t2.left)内层与外层对称镜像的核心要求
图解执行过程

以对称树为例:

text

1 / \ 2 2 / \ / \ 3 4 4 3

调用isMirror(2, 2)

java

// 第一层:两个节点都不为null 返回: (2 == 2) // ✓ 值相等 && isMirror(2.left=3, 2.right=3) // 递归进入第二层左 && isMirror(2.right=4, 2.left=4) // 递归进入第二层右

进入isMirror(3, 3)

java

// 第二层左:两个节点都不为null 返回: (3 == 3) // ✓ 值相等 && isMirror(3.left=null, 3.right=null) // 递归 && isMirror(3.right=null, 3.left=null) // 递归

进入isMirror(null, null)

java

// 第三层:两个都是null 返回: true // ✅ t1==null && t2==null

所以isMirror(3, 3)完整返回:

java

true && true && true = true

同样isMirror(4, 4)也会返回true

最终结果:

java

true && true && true = true
迭代法(BFS):

迭代法的思路也是一样,但我们这里使用的是队列来操作,我们创建一个队列,然后把根节点的左右节点入队,然后我们进入while循环,把这两个节点取出

然后我们进行条件判断,首先是判断两个左右节点时候都为null,如果都为null,我们直接continue,这里为什么不是直接返回true呢

java

if (t1 == null && t2 == null) continue;

意思是:

  • 这一对节点对称(都是空)

  • 不需要再检查它们的子节点(因为空节点没有子节点)

  • 继续检查队列中其他待比较的对

我们刚进入循环的时候肯定不是null,因为进入while循环的条件就是队列非空,防止的是后面的节点的null值。

以这棵树为例:

text

1 / \ 2 2 \ \ 3 3

第1轮:处理 (2, 2)

java

t1.left = null (2没有左孩子) t2.right = 3 (2的右孩子是3) t1.right = 3 (2的右孩子是3) t2.left = null (2没有左孩子) 入队顺序:[null, 3, 3, null] ↑ ↑ ↑ ↑ │ │ │ └── 第2对的右 │ │ └────── 第2对的左 │ └───────── 第1对的右 └────────────── 第1对的左

第2轮:取出 (null, 3)

  • 这时t1 == nullt2 != null

  • 发现不对称 → 返回 false

如果没有 null 判断,代码会在t1.val时抛出空指针异常

所以 null 判断的作用

判断作用
if (t1 == null && t2 == null) continue;两个都是 null,说明这对节点对称,跳过,继续检查下一对
if (t1 == null || t2 == null) return false;一个 null 一个不是 → 结构不对称
if (t1.val != t2.val) return false;两个都不是 null,但值不相等 → 数值不对称

入队顺序的核心逻辑

java

deque.offer(leftNode.left); // 第1个 deque.offer(rightNode.right); // 第2个 ← 和第1个是一对 deque.offer(leftNode.right); // 第3个 deque.offer(rightNode.left); // 第4个 ← 和第3个是一对

目的:让需要比较的两个节点在队列中紧挨着,这样取出来时自然成对。

图解:入队和取出的配对关系

text

当前正在比较:leftNode 和 rightNode 入队操作: ┌─────────────────────────────────────────┐ │ leftNode.left ─────┐ │ │ │ 成为一对 │ │ rightNode.right ────┘ │ │ │ │ leftNode.right ─────┐ │ │ │ 成为一对 │ │ rightNode.left ─────┘ │ └─────────────────────────────────────────┘ 队列内容:[L.left, R.right, L.right, R.left] ↑ ↑ ↑ ↑ └───┬───┘ └───┬───┘ 第1对 第2对

继续循环判断。


题目答案:

递归法:
/** * 递归法 */ public boolean isSymmetric1(TreeNode root) { return compare(root.left, root.right); } private boolean compare(TreeNode left, TreeNode right) { if (left == null && right != null) { return false; } if (left != null && right == null) { return false; } if (left == null && right == null) { return true; } if (left.val != right.val) { return false; } // 比较外侧 boolean compareOutside = compare(left.left, right.right); // 比较内侧 boolean compareInside = compare(left.right, right.left); return compareOutside && compareInside; }
迭代法:
/** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode() {} * TreeNode(int val) { this.val = val; } * TreeNode(int val, TreeNode left, TreeNode right) { * this.val = val; * this.left = left; * this.right = right; * } * } */ class Solution { public boolean isSymmetric(TreeNode root) { Queue<TreeNode> que=new LinkedList<>(); que.offer(root.left); que.offer(root.right); while(!que.isEmpty()){ TreeNode t1= que.poll(); TreeNode t2=que.poll(); if(t1==null&&t2==null){ continue; } if(t1==null||t2==null||t1.val!=t2.val){ return false; } que.offer(t1.left); que.offer(t2.right); que.offer(t1.right); que.offer(t2.left); } return true; }}

结语:如果对你有帮助,请点赞,关注,收藏,你的支持就是我最大的鼓励!

http://www.jsqmd.com/news/796708/

相关文章:

  • 2026年湖南高端系统门窗与别墅阳光房定制完全指南:隔音防潮性能深度横评 - 年度推荐企业名录
  • 终极英雄联盟LCU工具箱完整指南:从新手到高手的进阶之路
  • 别再死记硬背了!用‘知识卡片+思维导图’法搞定离散数学里的命题、谓词与代数系统
  • 2026年电力巡检场景深度评测:3家无人机电力巡检公司对比 - 速递信息
  • 2026国内成长营TOP9!广东省广州等地营地口碑出众广受好评 - 十大品牌榜
  • Speechless:终极免费微博备份工具,一键导出PDF永久保存你的数字记忆
  • 进口电动小流量调节阀:美国米勒EC10V,微米级精准掌控每一滴流体 - 米勒阀门
  • 基于 C# 实现的 Omron HostLink (FINS) 协议 PLC 通讯
  • 2026年汽车线束波纹管定制深度选购指南:昶力管业与高分子材料定制化解决方案 - 精选优质企业推荐官
  • STM32F070实战:用CubeMX搞定电容触摸屏的I2C转USB HID(附完整报告描述符解析)
  • OpenVSP参数化飞机设计完整教程:从零开始快速构建专业航空模型
  • 安平县美宏丝网制品有限公司:河道护栏全场景解决方案服务商 - 奔跑123
  • Hitboxer终极指南:3分钟解决游戏按键冲突,让你的键盘操作瞬间职业化
  • 明日方舟基建自动化:解放双手的智能管理方案
  • 明日方舟基建自动化管理终极指南:3步实现高效资源产出
  • 2026最新自热火锅_自热食品_冲泡速食_方便食品_懒人食品品牌推荐!国内优质品牌权威榜单发布,品类丰富实力可靠值得选择 - 十大品牌榜
  • 3步轻松解决Windows无法打开苹果照片的终极方案:HEIF Utility完全指南
  • 2026连云港干洗店大起底:本地权威测评排名全解析 - 速递信息
  • 2026年常州热缩管源头厂家深度选购指南:昶力管业与新能源汽车线束防护解决方案对标 - 精选优质企业推荐官
  • 官方认证|2026年国内五大正规明星代言 / 明星经纪服务公司排名,深圳星旺文化传媒有限公司综合实力遥遥领先,广东深圳等地 - 十大品牌榜
  • 夜莺传说服务器联机开服教程
  • 我的世界手机版烦人的村民整合包下载基岩国际版2026最新版
  • 5分钟搞定B站视频下载:从大会员4K到批量处理全攻略
  • 2026年5月北京昌平区代理记账公司哪家好?八大公司注册代办财税公司服务优选推荐 - 品牌智鉴榜
  • 2026南昌婚纱照深度测评|TOP5口碑机构横评 品质与性价比全解析 - charlieruizvin
  • 别再自己写轮子了!用Modbus Poll和Modbus Slave快速搞定工业协议调试(附详细配置截图)
  • 话费卡回收常见问题解析:闲置原因与回收方法 - 团团收购物卡回收
  • 5分钟掌握AI图层分离:让复杂插画秒变可编辑PSD
  • 终极免费音乐解锁工具:3步教你解锁加密音乐文件
  • Linux服务器内存告急?别慌,揪出那个叫xorg的‘内存大户’并优雅释放