对称二叉树[简单]

优质博文: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)大小的空间。
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/679907.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

YOLOv5改进 | Conv篇 | 利用YOLOv10提出的SCDown魔改YOLOv5进行下采样(附代码 + 结构图 + 添加教程)

一、本文介绍 本文给大家带来的改进机制是利用YOLOv10提出的SCDown魔改YOLOv5进行下采样&#xff0c;其是更高效的下采样。具体而言&#xff0c;其首先利用点卷积调整通道维度&#xff0c;然后利用深度卷积进行空间下采样。这将计算成本减少到和参数数量减少到。同时&#xff…

5.透明效果

实时渲染中要实现透明效果&#xff0c;通常会在渲染模型时控制它的透明通道&#xff08;Alpha channel&#xff09;。 当一个物体被渲染到屏幕上时&#xff0c;每个片元除了颜色和深度值之外&#xff0c;它还有另一个属性—透明度。 当透明度为1时&#xff0c;表示该像素是完…

信息系统项目管理师0141:产品范围和项目范围(9项目范围管理—9.1管理基础—9.1.1产品范围和项目范围)

点击查看专栏目录 文章目录 第9章 项目范围管理9.1 管理基础9.1.1 产品范围和项目范围 第9章 项目范围管理 项目范围管理包括确保项目做且只做所需的全部工作&#xff0c;以成功完成项目。项目范围管理主要在于定义和控制哪些工作应该包括在项目内&#xff0c;哪些不应该包含在…

Golang | Leetcode Golang题解之第131题分割回文串

题目&#xff1a; 题解&#xff1a; func partition(s string) (ans [][]string) {n : len(s)f : make([][]int8, n)for i : range f {f[i] make([]int8, n)}// 0 表示尚未搜索&#xff0c;1 表示是回文串&#xff0c;-1 表示不是回文串var isPalindrome func(i, j int) int8…

数据结构与算法之Floyd弗洛伊德算法求最短路径

目录 前言 Floyd弗洛伊德算法 定义 步骤 一、初始化 二、添加中间点 三、迭代 四、得出结果 时间复杂度 代码实现 结束语 前言 今天是坚持写博客的第18天&#xff0c;希望可以继续坚持在写博客的路上走下去。我们今天来看看数据结构与算法当中的弗洛伊德算法。 Flo…

如何学习SQL?YouTube近百万粉丝技术频道的学习路径图。

大家好&#xff0c;我是王有志&#xff0c;一个分享硬核 Java 技术的金融摸鱼侠&#xff0c;欢迎大家加入 Java 人自己的交流群“共同富裕的 Java 人”。 ByteByteGo 频道在 5 月 30 日的通信邮件中提到了“How to Learn SQL”这一主题&#xff0c;并给出了一张详细的学习路径…

python——网络编程

流程图 面向连接的套接字 面向连接的通信提供序列化的、可靠的和不重复的数据交付&#xff0c;而没有记录边界。主要的协议是传输控制协议&#xff08;TCP&#xff09;; TCP套接字&#xff0c;在python中&#xff0c;必须使用SOCK_STREAM作为套接字类型 tcp的特点 面向连接…

使用GitHub托管静态网页

前言​&#xff1a; 如果没有服务器&#xff0c;也没有域名&#xff0c;又想部署静态网页的同学&#xff0c;那就可以尝试使用GitHub托管自己的网页​。 正文&#xff1a; 首先要有自己的GitHub的账号&#xff0c;如果没有可以自己搜索官网进行注册登录&#xff0c;国内对Gi…

深入了解 C 语言 Bug

目录 一、引言二、Bug的定义三、Bug的由来四、Bug的影响五、应对 Bug 的方法六、结论 一、引言 1、在 C 语言的编程世界中&#xff0c;Bug 是一个我们无法回避的话题。 2、Bug&#xff0c;简单来说&#xff0c;就是程序中存在的错误或缺陷。它可以表现为程序运行结果的异常、崩…

容器运行nslookup提示bash: nslookup: command not found【笔记】

在容器中提示bash: nslookup: command not found&#xff0c;表示容器中没有安装nslookup命令。 可以通过以下命令安装nslookup&#xff1a; 对于基于Debian/Ubuntu的容器&#xff0c;使用以下命令&#xff1a; apt-get update apt-get install -y dnsutils对于基于CentOS/R…

机器学习、深度学习模型建模开发过程中常见的评估指标汇总学习记录

在机器学习、深度学习模型的开发过程中&#xff0c; 很重要的一个环节就是要对模型的性能进行评估分析&#xff0c;不同类型的任务不同的模型对应使用不同的评估指标体系&#xff0c;本文的主要目的是正好趁着最近有这块的需求&#xff0c;就想着找点时间把汇总学习的内容整理记…

TypeScript学习(一):开发环境搭建

官方文档搭建参考 https://learn.microsoft.com/zh-cn/training/modules/typescript-get-started/ 1.下载node.js https://nodejs.org/en/download 2.下载vscode https://code.visualstudio.com/ 3.在线ts的测试工具 https://www.typescriptlang.org/play/ 4.下载typescr…

Linux线程安全:线程互斥

一、线程互斥的概念 1.1临界资源与互斥的关系 临界资源&#xff1a;多线程执行流共享的资源就叫做临界资源。 临界区&#xff1a;每个线程内部&#xff0c;访问临界资源的代码&#xff0c;就叫做临界区。 互斥&#xff1a;任何时刻&#xff0c;互斥保证有且只有一个执行流进入…

274 基于matlab的随机粗糙表面对微气体轴承内气体压强分布的影响

基于matlab的随机粗糙表面对微气体轴承内气体压强分布的影响。采用差分法求解气体轴承的雷诺方程&#xff0c;通过尺寸参数、分形维数对粗糙度表面设置&#xff0c;滑流参数设置&#xff0c;实现气压分布可视化结果显示。程序已调通&#xff0c;可直接运行。 274 气体轴承 随机…

软件设计,建模及需求分析

文章目录 设计原则建模及需求分析重构 设计原则 SOLID原则 单一职责 开闭 &#xff08;扩展开放&#xff0c;修改关闭&#xff09; 里氏替换 &#xff08;父类出现地方都可以用子类替换&#xff09; 接口隔离 依赖倒置&#xff08;高层模块不依赖低层&#xff0c;两层都依…

[数据集][图像分类]茶叶叶子病害分类数据集304张4类别

数据集类型&#xff1a;图像分类用&#xff0c;不可用于目标检测无标注文件 数据集格式&#xff1a;仅仅包含jpg图片&#xff0c;每个类别文件夹下面存放着对应图片 图片数量(jpg文件个数)&#xff1a;304 分类类别数&#xff1a;4 类别名称:[“anthracnose”,“bird_eye_spot”…

三维模型轻量化工具:手工模型、BIM、倾斜摄影等皆可用!

老子云是全球领先的数字孪生引擎技术及服务提供商&#xff0c;它专注于让一切3D模型在全网多端轻量化处理与展示&#xff0c;为行业数字化转型升级与数字孪生应用提供成套的3D可视化技术、产品与服务。 老子云是全球领先的数字孪生引擎技术及服务提供商&#xff0c;它专注于让…

端口映射如何检测?

端口映射是一种网络通信技术&#xff0c;它允许将公网IP地址的特定端口指向内部局域网中的特定设备或应用程序。通过端口映射&#xff0c;可以实现远程访问内部设备&#xff0c;解决了网络环境限制的问题。 在进行端口映射之前&#xff0c;需要进行端口映射检测&#xff0c;以确…

JS:setTimeout计时器优化

setTimeout会因为浏览器的事件循环机制导致计时器的误差&#xff0c;JS代码越复杂、越多&#xff0c;误差越大。 通过使用performance.now()可以一定程度上减小这个误差值。 performance.now()返回的是一个浮点数&#xff0c;表示从页面加载到现在的毫秒数&#xff0c;精度可…

动态数组的实现(仿写ArrayList)

动态数组是什么 之前写过一篇数组和静态数组的介绍&#xff1a;数组的定义和特点&#xff0c;静态数组CURD的实现 我们在静态数组的基础上&#xff0c;增加一些比较方便的功能&#xff0c;比如自动扩容&#xff0c;获取数组长度等&#xff0c;这样的数组叫动态数组 动态数组…