101.对称二叉树 | 递归 + 迭代

news/2024/11/8 17:14:18/

对称二叉树

leetcode : https://leetcode.cn/problems/symmetric-tree/

参考 对称二叉树

递归思路

首先在开始时, 一定要注意, 对称二叉树对比的并不是一个节点的左右子树, 而是两棵树, 这个很关键!

image-20230111211254708

对比时是内侧和内侧对比, 外侧和外侧对比,

递归三步 :

  1. 确定递归的参数以及返回值

    本题中需要去对比内侧和外侧节点是否对称, 所以返回值是 boolean 类型

     private boolean compare(TreeNode left, TreeNode right)
    
  2. 确定终止条件 :

    • 我们在对比两棵树是否对称时, 主要分为以下几种情况

    • 左节点为空, 右节点不为空, 不对称 (注意这里是左节点和右节点, 而不是左子树和右子树)

    • 左节点不为空, 右节点为空, 不对称

    • 左右节点都为空, 对称

    • 左右节点都不为空, 此时要比较二者的值

image-20230111211746071
 		// 终止条件 : 避免操作空指针// 1. 左节点为空, 右节点不为空 不对称if(left == null && right != null) {return false;}// 2. 左节点不为空, 右节点为空 不对称if(left != null && right == null) {return false;}// 3. 左节点为空, 右节点为空 对称if(left == null && right == null) {return true;}
  1. 确定当前层逻辑
  • 在确定了终止条件为空的情况下, 当前层的逻辑是 判断两个节点值是否相同
  • 然后分别对比两棵树的内侧和外侧的节点
  		if(left.val != right.val) {return false;}// 1. 对比内侧boolean inside = compare(left.right, right.left);// 2. 对比外侧boolean outside = compare(left.left, right.right);return inside && outside;

递归流程

初始状态 : 传入 left 和 right

image-20230111213511399

首先是会判断是否存在 left 或者 right 为空的情况(终止条件) , 这个也是为了防止处理空节点

然后我们要对比以 left 为根节点 和 以right 为根节点的树, 如下图所示, 这个很关键

image-20230111213710704

首先对比内侧的 :

boolean inside = compare(left.right, right.left);

image-20230111213848145

同理, 我们对比内侧其实就是对比的 left.right 和 right.left 这两棵子树是否对称

我们假设, 当前的树不再向下延伸(这棵树就这么大), 此时的逻辑是

  1. 先判断是否满足终止条件, 也就是存在 left.right 或者 right.left 为空的情况, 此时不对称, 直接就返回结果了

    boolean inside = compare(left.right, right.left);
    

    inside = false , 直接结束

  2. 假设没有到达终止条件, 先比较 left.right.val 和 right.left.val 是否相等

  3. 比较内侧和外侧的节点是否对称

  4. 最后会返回 left.right 和 right.left 这两棵树的是否对称的结果

需要补充的是, 当最后到达叶子节点时, 其实叶子节点也可以看做左右子节点都为空的树

image-20230111214540654

如上图所示, 此时他们会被下面的代码处理

// 3. 左节点为空, 右节点为空 对称if(left == null && right == null) {return true;}

递归代码

/*** 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) {return compare(root.left, root.right);}private boolean compare(TreeNode left, TreeNode right) {// 终止条件 : 避免操作空指针// 1. 左节点为空, 右节点不为空 不对称if(left == null && right != null) {return false;}// 2. 左节点不为空, 右节点为空 不对称if(left != null && right == null) {return false;}// 3. 左节点为空, 右节点为空 对称if(left == null && right == null) {return true;}// 当前层的处理逻辑 : 左右子树都不为空if(left.val != right.val) {return false;}// 下一层// 1. 对比内侧boolean inside = compare(left.right, right.left);// 2. 对比外侧boolean outside = compare(left.left, right.right);return inside && outside;}}

迭代思路

迭代思路和递归思路有一些相似, 都是外侧和外侧对比, 内侧和内侧对比 !

核心的点就是把每一层的取出来, 然后按照 内侧对内侧 和 外侧对外侧的顺序存入队列

这样的话, 每次取出栈顶的两个都是一对的

image-20230111223028579

如上图, 核心点是存入队列的时候, 存入的顺序是成对的!

因为取出来正好的成对的, 这样取出节点后, 我们只需要判断是否对称即可

  1. 左右节点都为空, 不处理, 直接跳过 (对称)
  2. 左节点为空, 右节点不为空 (不对称)
  3. 左节点不为空, 右节点为空 (不对称)
  4. 左右节点都不为空, 比较两个节点的值是否相同

迭代代码

需要注意的是 , LinkedList 是可以存储null值的, 其他的数据结构不一定支持

/*** 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> queue = new LinkedList<>();queue.add(root.left);queue.add(root.right);while(!queue.isEmpty()) {TreeNode left = queue.poll();TreeNode right = queue.poll();// 判断// 1. 左空, 右不空, 不对称if(left == null && right != null ) {return false;}// 2. 左不为空, 右为空 不对称if (left != null && right == null) {return false;}// 左右都为空, 就不处理if(left == null && right == null) {continue;}// 左右都不为空的情况, 比较二者的值if(left.val != right.val) {return false;}// 将下一层子节点添加到队列// 注意, 要按照对称的顺序, 外侧对外侧, 内侧对内侧// left.left 和 right.right// left.right 和 right.left// 外侧queue.add(left.left);queue.add(right.right);// 内侧queue.add(left.right);queue.add(right.left);}return true;}
}

http://www.ppmy.cn/news/11395.html

相关文章

Linux操作系统常用命令

✅作者简介&#xff1a;热爱国学的Java后端开发者&#xff0c;修心和技术同步精进。 &#x1f34e;个人主页&#xff1a;Java Fans的博客 &#x1f34a;个人信条&#xff1a;不迁怒&#xff0c;不贰过。小知识&#xff0c;大智慧。 &#x1f49e;当前专栏&#xff1a;Java案例分…

MyBatis批量插入的五种方式

MyBatis利用For循环批量插入MyBatis的手动批量提交MyBatis以集合方式批量新增&#xff08;推荐&#xff09;MyBatis-Plus提供的SaveBatch方法MyBatis-Plus提供的InsertBatchSomeColumn方法&#xff08;推荐&#xff09; 文章目录1.项目准备1.1 pom文件1.2 yml文件1.3 User类2.M…

大二层网络概述

要想了解大二层网络&#xff0c;必须要先了解传统三层网络和传统二层网络&#xff0c;最后根据大二层网络和后者的区别&#xff0c;可以清晰地了解大二层网络。 传统三层网络 传统数据中心采用三层网络架构&#xff0c;即整个网络由接入层、汇聚层和核心层组成&#xff0c;流…

Linux驱动开发基础__ Linux中断系统中的重要数据结构

目录 1 整体概述 2 irq_desc 数组 3 irqaction 结构体 4 irq_data 结构体 5 irq_domain 结构体 6 irq_chip 结构体 1 整体概述 该文章内容&#xff0c;可以从 request_irq(include/linux/interrupt.h)函数一路分析得到。 能弄清楚下面这个图&#xff0c;对 Linux 中…

Dbeaver连接ES问题一站解决

前言 最近几天一直做ES的TPS测试&#xff0c;每次看数据ES的数据都在嫌麻烦&#xff08;在postman指定索引通过url请求查看数据&#xff09;。最后决定还是整整Dbeaver连接ES。 一、当前境况 1、ES版本比较老&#xff0c;还是6.4.2的 2、Dbeaver直接连接已经提示支持8.x版本 3…

学习python,我使用代码悄悄集齐了五福~哎嘿嘿

啊哈哈哈哈&#xff0c;我又又又来啦 这不是快春节了吗&#xff0c;支付宝等一些集五福活动又又又又一次的到来 今天呢&#xff0c;写一个啥呀我也不晓得&#xff0c;啊哈哈哈哈哈 今天写一个%90会出敬业福哦&#xff0c;啊哈哈哈哈 1.制作文字福 这个其实挺“简单”的&…

【C语言】内存函数介绍

它们所在的头文件&#xff1a; &#xff08;这里出现的arr都为char类型数组&#xff09;strlen作用&#xff1a;计算一个字符串的长度本质&#xff1a;历经千辛找一个 \0 &#xff0c;找到 \0 就立马停止。&#xff08;就是找 \0 &#xff09;易错&#xff1a;strlen 返回值为 …

Replicate Brogaard Stock Volatility Decomposition

文章目录IntroductionData and SampleDownload DataClean DataExtract Estimation Unit and Set Global VariablesImplement Brogaard DecompositionEstimate VAR Coefficients, Matrix BBB, ϵt\epsilon_tϵt​, Σe\Sigma_eΣe​, and Σϵ\Sigma_\epsilonΣϵ​Estimate 15-…