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

对称二叉树[简单]

优质博文:IT-BLOG-CN
在这里插入图片描述

一、题目

给你一个二叉树的根节点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

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

二、代码

【1】递归: 我们将一个树的左右节点相同,转换为两个根节点具有相同的值,每个树的右子树都与另一个树的左子树镜像对称。我们通过一个递归函数,通过同步移动两个指针的方式来遍历树,rootLeftrootRight都指向一个树的根,然后rootLeft右移时,rootRight左移,rootLeft左移时,rootRight右移。检查rootLeftrootRight的值是否相等,如果相等再判断左右子树是否对称。

/*** 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 check(root, root);}private boolean check(TreeNode rootLeft, TreeNode rootRight) {if (rootLeft == null && rootRight == null) {return true;}if (rootLeft == null || rootRight == null) {return false;}return rootLeft.val == rootRight.val && check(rootLeft.left, rootRight.right) && check(rootLeft.right, rootRight.left);}
}
**时间复杂度:** 这里遍历了这棵树,渐进时间复杂度为`O(n)`。  
**空间复杂度:** 这里的空间复杂度和递归使用的栈空间有关,这里递归层数不超过`n`,故渐进空间复杂度为`O(n)`。

【2】迭代: 我们引入一个队列,这是把递归程序改写成迭代程序的常用方法。初始化时我们把根节点入队两次。每次提取两个结点并比较它们的值(队列中每两个连续的结点应该是相等的,而且它们的子树互为镜像),然后将两个结点的左右子结点按相反的顺序插入队列中。当队列为空时,或者我们检测到树不对称(即从队列中取出两个不相等的连续结点)时,该算法结束。

/*** 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 check(root, root);}private boolean check(TreeNode rootLeft, TreeNode rootRight) {Queue<TreeNode> q = new LinkedList<TreeNode>();q.offer(rootLeft);q.offer(rootRight);while(!q.isEmpty()) {rootLeft = q.poll();rootRight = q.poll();if (rootLeft == null && rootRight == null) {continue;}if ((rootLeft == null || rootRight == null) || (rootLeft.val != rootRight.val)) {return false;}q.offer(rootLeft.left);q.offer(rootRight.right);q.offer(rootLeft.right);q.offer(rootRight.left);}return true;}
}

时间复杂度: 这里遍历了这棵树,渐进时间复杂度为O(n)
空间复杂度: 这里需要用一个队列来维护节点,每个节点最多进队一次,出队一次,队列中最多不会超过n个点,故渐进空间复杂度为O(n)

【3】对称二叉树定义: 对于树中 任意两个对称节点LR,一定有:
L.val = R.val :即此两对称节点值相等。
L.left.val = R.right.val :即L的 左子节点 和R的 右子节点 对称。
L.right.val = R.left.val :即L的 右子节点 和R的 左子节点 对称。
根据以上规律,考虑从顶至底递归,判断每对左右节点是否对称,从而判断树是否为对称二叉树。

算法流程: 函数isSymmetric(root)
【1】特例处理: 若根节点 root 为空,则直接返回 truetruetrue 。
【2】返回值: 即 recur(root.left, root.right) ;

函数recur(L, R)
终止条件:
1、当 L 和 R 同时越过叶节点: 此树从顶至底的节点都对称,因此返回 truetruetrue 。
2、当 L 或 R 中只有一个越过叶节点: 此树不对称,因此返回 falsefalsefalse 。
3、当节点 L 值 ≠ 节点 R 值: 此树不对称,因此返回 falsefalsefalse 。

递推工作:
1、判断两节点 L.left 和 R.right 是否对称,即 recur(L.left, R.right) 。
2、判断两节点 L.right 和 R.left 是否对称,即 recur(L.right, R.left) 。
3、返回值: 两对节点都对称时,才是对称树,因此用与逻辑符 && 连接。
在这里插入图片描述

class Solution {public boolean isSymmetric(TreeNode root) {return root == null || recur(root.left, root.right);}boolean recur(TreeNode L, TreeNode R) {if (L == null && R == null) return true;if (L == null || R == null || L.val != R.val) return false;return recur(L.left, R.right) && recur(L.right, R.left);}
}

复杂度分析:
时间复杂度O(N) 其中N为二叉树的节点数量,每次执行recur()可以判断一对节点是否对称,因此最多调用N/2recur()方法。
空间复杂度O(N) 如下图所示,最差情况下(二叉树退化为链表),系统使用O(N)大小的空间。
在这里插入图片描述

相关文章:

对称二叉树[简单]

优质博文&#xff1a;IT-BLOG-CN 一、题目 给你一个二叉树的根节点root&#xff0c; 检查它是否轴对称。 示例 1&#xff1a; 输入&#xff1a;root [1,2,2,3,4,4,3] 输出&#xff1a;true 示例 2&#xff1a; 输入&#xff1a;root [1,2,2,null,3,null,3] 输出&#xf…...

判断GIF类型并使用ImageDecoder解析GIF图

一、判断是否为GIF图片类型 在JavaScript中&#xff0c;判断用户上传的文件是否为GIF文件类型时&#xff0c;通常可以通过检查文件的type属性或文件的拓展名来判断&#xff0c;但是由于文件拓展名可以轻易被用户修改&#xff0c;type属性是由浏览器根据文件拓展名猜测得出的&a…...

数组对象数据修改后页面没有更新,无法进行编辑,校验失效问题

在 Vue 中&#xff0c;当你通过 Object.assign 或其他方式修改了对象中的某个属性时&#xff0c;Vue 并不会触发组件重新渲染&#xff0c;因此表单中的 input 框无法及时更新。这可能导致在修改表单数据后&#xff0c;页面没有更新&#xff0c;而且表单校验也失效的情况。这是因…...

什么是低代码?有什么特点?

低代码是一种高效的软件开发方法&#xff0c;它允许开发者通过图形化界面和预构建的代码块&#xff0c;以最小化传统手写代码的方式快速构建应用程序。这种方法旨在加速应用程序的开发周期&#xff0c;同时降低技术门槛和成本。以下是根据驰骋低代码设计者的观念与主张&#xf…...

Kafka 消息保留时长由 24 小时变更为 72 小时的影响分析

目录 Kafka 消息保留时长由 24 小时变更为 72 小时的影响分析Kafka 消息存储机制保留时长对生产速度的影响保留时长对消费速度的影响底层分析与优化建议附加&#xff1a;将 Kafka 消息保留时长从 24 小时更改为 72 小时后&#xff0c;CPU 使用率从 40% 上升到 70% 的现象1. 增加…...

MySQL A表的字段值更新为B表的字段值

MySQL A表的字段值更新为B表的字段值 准备数据表 create table person (id int unsigned auto_increment comment 主键 primary key,uuid varchar(32) not null comment 系统唯一标识符32个长度的字符串,mobile varchar(11) null comment 中国国内手机号,nickn…...

TCP 建链(三次握手)和断链(四次握手)

TCP 建链&#xff08;三次握手&#xff09;和断链&#xff08;四次挥手&#xff09; 背景简介建链&#xff08;三次握手&#xff09;断链&#xff08;四次挥手&#xff09;序号及标志位延伸问题为什么建立连接需要握手三次&#xff0c;两次行不行&#xff1f;三次握手可以携带数…...

SpringBoot集成JOOQ加Mybatis-plus使用@Slf4j日志

遇到个问题记录下&#xff0c;就是SpringBoot使用Mybatis和Mybatis-plus时可以正常打印日志&#xff0c;但是JOOQ的操作日志确打印不出来&#xff1f; 下面的解决方法就是将JOOQ的日志单独配置出来&#xff0c;直接给你们配置吧&#xff01; 在项目的resources目录下创建日志…...

浅谈JavaScript中的对象赋值

目录 常见的对象赋值方式 直接赋值和对象扩展&#xff08;浅拷贝&#xff09;两种赋值方式区别 区别 联系 常见的对象赋值方式 1. 直接赋值&#xff1a;this.info this.deviceInfo&#xff0c;将一个对象的引用赋给另一个变量&#xff0c;它们引用同一个对象。 2. 对象扩…...

Java面试题-集合

Java面试题-集合 1、什么是集合&#xff1f;2、集合和数组的区别是什么&#xff1f;3、集合有哪些特点&#xff1f;4、常用的集合类有哪些&#xff1f;5、List&#xff0c; Set&#xff0c; Map三者的区别&#xff1f;6、说说集合框架底层数据结构&#xff1f;7、线程安全的集合…...

从当当网批量获取图书信息

爬取当当网图书数据并保存到本地&#xff0c;使用request、lxml的etree模块、pandas保存数据为excel到本地。 爬取网页的url为&#xff1a; http://search.dangdang.com/?key{}&actinput&page_index{} 其中key为搜索关键字&#xff0c;page_index为页码。 爬取的数据…...

python爬虫之JS逆向——网页数据解析

目录 一、正则 1 正则基础 元字符 基本使用 通配符: . 字符集: [] 重复 位置 管道符和括号 转义符 转义功能 转义元字符 2 正则进阶 元字符组合(常用) 模式修正符 re模块的方法 有名分组 compile编译 二、bs4 1 四种对象 2 导航文档树 嵌套选择 子节点、…...

VL53L4CX TOF开发(2)----修改测距范围及测量频率

VL53L4CX TOF开发.2--修改测距范围及测量频率 概述视频教学样品申请完整代码下载测距范围测量频率硬件准备技术规格系统框图应用示意图生成STM32CUBEMX选择MCU串口配置IIC配置 XSHUTGPIO1X-CUBE-TOF1app_tof.c详细解释测量频率修改修改测距范围 概述 最近在弄ST和瑞萨RA的课程…...

C++之noexcept

目录 1.概述 2.noexcept作为说明符 3.noexcept作为运算符 4.传统throw与noexcept比较 5.原理剖析 6.总结 1.概述 在C中&#xff0c;noexcept是一个关键字&#xff0c;用于指定函数不会抛出异常。如果函数保证不会抛出异常&#xff0c;编译器可以进行更多优化&#xff0c;…...

Kafka之Broker原理

1. 日志数据的存储 1.1 Partition 1. 为了实现横向扩展&#xff0c;把不同的数据存放在不同的 Broker 上&#xff0c;同时降低单台服务器的访问压力&#xff0c;我们把一个Topic 中的数据分隔成多个 Partition 2. 每个 Partition 中的消息是有序的&#xff0c;顺序写入&#x…...

RabbitMQ docker安装及使用

1. docker安装RabbitMQ docker下载及配置环境 docker pull rabbitmq:management # 创建用于挂载的目录 mkdir -p /home/docker/rabbitmq/{data,conf,log} # 创建完成之后要对所创建文件授权权限&#xff0c;都设置成777 否则在启动容器的时候容易失败 chmod -R 777 /home/doc…...

篇3:Mapbox Style Specification

接《篇2:Mapbox Style Specification》,继续解读Mapbox Style Specification。 目录 Spec Reference Root 附录: MapBox Terrain-RGB...

C#WPF数字大屏项目实战11--质量控制

1、区域划分 2、区域布局 3、视图模型 4、控件绑定 5、运行效果 走过路过&#xff0c;不要错过&#xff0c;欢迎点赞&#xff0c;收藏&#xff0c;转载&#xff0c;复制&#xff0c;抄袭&#xff0c;留言&#xff0c;动动你的金手指&#xff0c;财务自由...

第九十七节 Java面向对象设计 - Java Object.Finalize方法

Java面向对象设计 - Java Object.Finalize方法 Java提供了一种在对象即将被销毁时执行资源释放的方法。 在Java中&#xff0c;我们创建对象&#xff0c;但是我们不能销毁对象。 JVM运行一个称为垃圾收集器的低优先级特殊任务来销毁不再引用的所有对象。 垃圾回收器给我们一个…...

【scikit-learn009】异常检测系列:单类支持向量机(OC-SVM)实战总结(看这篇就够了,已更新)

1.一直以来想写下机器学习训练AI算法的系列文章,作为较火的机器学习框架,也是日常项目开发中常用的一款工具,最近刚好挤时间梳理、总结下这块儿的知识体系。 2.熟悉、梳理、总结下scikit-learn框架OCSVM模型相关知识体系。 3.欢迎批评指正,欢迎互三,跪谢一键三连! 4.欢迎…...

第19节 Node.js Express 框架

Express 是一个为Node.js设计的web开发框架&#xff0c;它基于nodejs平台。 Express 简介 Express是一个简洁而灵活的node.js Web应用框架, 提供了一系列强大特性帮助你创建各种Web应用&#xff0c;和丰富的HTTP工具。 使用Express可以快速地搭建一个完整功能的网站。 Expre…...

零门槛NAS搭建:WinNAS如何让普通电脑秒变私有云?

一、核心优势&#xff1a;专为Windows用户设计的极简NAS WinNAS由深圳耘想存储科技开发&#xff0c;是一款收费低廉但功能全面的Windows NAS工具&#xff0c;主打“无学习成本部署” 。与其他NAS软件相比&#xff0c;其优势在于&#xff1a; 无需硬件改造&#xff1a;将任意W…...

CTF show Web 红包题第六弹

提示 1.不是SQL注入 2.需要找关键源码 思路 进入页面发现是一个登录框&#xff0c;很难让人不联想到SQL注入&#xff0c;但提示都说了不是SQL注入&#xff0c;所以就不往这方面想了 ​ 先查看一下网页源码&#xff0c;发现一段JavaScript代码&#xff0c;有一个关键类ctfs…...

SCAU期末笔记 - 数据分析与数据挖掘题库解析

这门怎么题库答案不全啊日 来简单学一下子来 一、选择题&#xff08;可多选&#xff09; 将原始数据进行集成、变换、维度规约、数值规约是在以下哪个步骤的任务?(C) A. 频繁模式挖掘 B.分类和预测 C.数据预处理 D.数据流挖掘 A. 频繁模式挖掘&#xff1a;专注于发现数据中…...

LeetCode - 394. 字符串解码

题目 394. 字符串解码 - 力扣&#xff08;LeetCode&#xff09; 思路 使用两个栈&#xff1a;一个存储重复次数&#xff0c;一个存储字符串 遍历输入字符串&#xff1a; 数字处理&#xff1a;遇到数字时&#xff0c;累积计算重复次数左括号处理&#xff1a;保存当前状态&a…...

Opencv中的addweighted函数

一.addweighted函数作用 addweighted&#xff08;&#xff09;是OpenCV库中用于图像处理的函数&#xff0c;主要功能是将两个输入图像&#xff08;尺寸和类型相同&#xff09;按照指定的权重进行加权叠加&#xff08;图像融合&#xff09;&#xff0c;并添加一个标量值&#x…...

C# SqlSugar:依赖注入与仓储模式实践

C# SqlSugar&#xff1a;依赖注入与仓储模式实践 在 C# 的应用开发中&#xff0c;数据库操作是必不可少的环节。为了让数据访问层更加简洁、高效且易于维护&#xff0c;许多开发者会选择成熟的 ORM&#xff08;对象关系映射&#xff09;框架&#xff0c;SqlSugar 就是其中备受…...

tree 树组件大数据卡顿问题优化

问题背景 项目中有用到树组件用来做文件目录&#xff0c;但是由于这个树组件的节点越来越多&#xff0c;导致页面在滚动这个树组件的时候浏览器就很容易卡死。这种问题基本上都是因为dom节点太多&#xff0c;导致的浏览器卡顿&#xff0c;这里很明显就需要用到虚拟列表的技术&…...

以光量子为例,详解量子获取方式

光量子技术获取量子比特可在室温下进行。该方式有望通过与名为硅光子学&#xff08;silicon photonics&#xff09;的光波导&#xff08;optical waveguide&#xff09;芯片制造技术和光纤等光通信技术相结合来实现量子计算机。量子力学中&#xff0c;光既是波又是粒子。光子本…...

【JVM面试篇】高频八股汇总——类加载和类加载器

目录 1. 讲一下类加载过程&#xff1f; 2. Java创建对象的过程&#xff1f; 3. 对象的生命周期&#xff1f; 4. 类加载器有哪些&#xff1f; 5. 双亲委派模型的作用&#xff08;好处&#xff09;&#xff1f; 6. 讲一下类的加载和双亲委派原则&#xff1f; 7. 双亲委派模…...