二叉树(下)

news2024/11/13 10:11:33

目录

判断树是否相同

判断树是不是另一棵树的子树

二叉树翻转

判断平衡二叉树

 二叉树层序遍历


这篇主要提供一些关于二叉树例题的讲解,如果对二叉树及其基本操作有疑问的可以转至:

二叉树(上)-CSDN博客
二叉树(中)-CSDN博客

判断树是否相同

力扣链接:100. 相同的树 - 力扣(LeetCode)

题目描述:

给你两棵二叉树的根节点 p 和 q ,编写一个函数来检验这两棵树是否相同。如果两个树在结构上相同,并且节点具有相同的值,则认为它们是相同的。

思路

这里主要从两方面去思考两棵树是否相同:结构和数值。分别是对应下面的图片

这道题的难点在于如何把这个思路进行代码形式的转换。

首先我们可以先判断结构是否相同,

        if(p != null && q == null || p == null && q != null){
            return false;
        }

剩下的两种情况为:两者都为空 或者 两者都不为空,再排除掉两者都为空的情况,

        if(p == null && q == null){
            return true;
        }

接着判断其中的值是否相同,

        if(p.val != q.val){
            return false;
        }

最后存留下来的情况是:值都不为空且值一样,此时就可以继续进行递归来保证两棵树的每一个节点都是一样的。

return isSameTree(p.left, q.left) && isSameTree(p.right, q.right);

完整代码为

//时间复杂度, min(p, q)
class Solution {
    public boolean isSameTree(TreeNode p, TreeNode q) {
        //1.先判断结构是否相同
        if(p != null && q == null || p == null && q != null){
            return false;
        }
        //2.剩下的两种情况为 空或者相等
        if(p == null && q == null){
            return true;
        }
        //都不为空,判断值是否一样
        if(p.val != q.val){
            return false;
        }
        //都不为空且值一样
        return isSameTree(p.left, q.left) && isSameTree(p.right, q.right);
    }
}

判断树是不是另一棵树的子树

力扣链接:572. 另一棵树的子树 - 力扣(LeetCode)

情况可以大致分为以下三种:

 思路为:

  1. 当前子树和根节点是否一样?
  2. 判断子树是不是和当前root的左子树一样?
  3. 判断子树是不是和当前root的右子树一样?

这里其实也调用了上面写的 判断树是否相同 的代码,

先用 root 和 subRoot(子树) 进行判断树是否相同,然后用root的左子树和右子树同subroot进行递归比较,分别进行比较和返回。

注意:先是比较两棵树是否为子树关系,然后进行递归。

//时间复杂度
//root共有节点r个,subRoot共有节点s个
//时间复杂度为O(r * s)
class Solution {
    public boolean isSubtree(TreeNode root, TreeNode subRoot) {
        if(root == null){
            return false;
        }
        if(isSameTree(root, subRoot)) return true;
        if(isSubtree(root.left, subRoot)) return true;
        if(isSubtree(root.right , subRoot)) return true;

        return false;
    }

    public boolean isSameTree(TreeNode p, TreeNode q) {
        //1.先判断结构是否相同
        if(p != null && q == null || p == null && q != null){
            return false;
        }
        //2.剩下的两种情况为 空或者相等
        if(p == null && q == null){
            return true;
        }
        //都不为空,判断值是否一样
        if(p.val != q.val){
            return false;
        }
        //都不为空且值一样
        return isSameTree(p.left, q.left) && isSameTree(p.right, q.right);
    }
    
}

二叉树翻转

力扣链接:226. 翻转二叉树 - 力扣(LeetCode)

 

 主要思路其实和数据的交换位置是一个类型的,像是下面的代码部分

        TreeNode tmp = root.left;
        root.left = root.right;
        root.right = tmp;

然后进行递归,同时加上递归条件和特定情况

class Solution {
    public TreeNode invertTree(TreeNode root) {
        if(root == null){
            return root;
        }
        //避免叶子节点再进行
        if(root.left == null && root.right == null){
            return null;
        }
        TreeNode tmp = root.left;
        root.left = root.right;
        root.right = tmp;
        invertTree(root.left);
        invertTree(root.right);

        return root;
    }
}

判断平衡二叉树

力扣链接:110. 平衡二叉树 - 力扣(LeetCode)

平衡二叉树:如果一棵树是二叉树,那么它的每棵子树都是平衡二叉树。

左右子树高度差 <=1;如果 >=2 则不是平衡二叉树

思路:遍历这棵树的节点,求每个节点的左树和右树的高度,如果发现h >=2,则返回false。

判断整棵树会发现根节点的左子树为平衡二叉树,右子树也是平衡二叉树。

 这里可以先尝试把框架搭建出来:求左子树的高度和右子树的高度,

    public boolean isBalanced(TreeNode root) {
        if(root == null){
            return true;
        }

        int leftHeight = getHeight(root.left);
        int rightHeight = getHeight(root.right);

        return Math.abs(leftHeight - rightHeight) < 2
        && isBalanced(root.left) && isBalanced(root.right);
    }

因为要求每棵树的左右树高,所以我们需写一个额外的方法来进行。

    public int getHeight(TreeNode root){
        if(root == null){
            return 0;
        }
        int leftTree = getHeight(root.left);
        int rightTree = getHeight(root.right);

        return leftTree > rightTree ? leftTree + 1 : rightTree +1;
    }

完整代码为

//时间复杂度为O(N^2)
class Solution {
    public boolean isBalanced(TreeNode root) {
        if(root == null){
            return true;
        }

        int leftHeight = getHeight(root.left);
        int rightHeight = getHeight(root.right);

        return Math.abs(leftHeight - rightHeight) < 2
        && isBalanced(root.left) && isBalanced(root.right);

    }

    public int getHeight(TreeNode root){
        if(root == null){
            return 0;
        }
        int leftTree = getHeight(root.left);
        int rightTree = getHeight(root.right);

        return leftTree > rightTree ? leftTree + 1 : rightTree +1;
    }
}

 二叉树层序遍历

力扣链接:102. 二叉树的层序遍历 - 力扣(LeetCode)

第一种方法:队列

思路:主要是依靠队列来实现层序遍历,先把头节点设为cur,询问队列时候为空,再去除头节点,并输出,若左右子树不为则分别放入左右子树 

public void levelOrder(TreeNode root){
    if(root == null){
        return;
    }
    Queue<TreeNode> queue = new LinkedList<>();
    queue.offer(root);

    while(!queue.isEmpty()){
        TreeNode cur = queue.poll();
        System.out.print(cur.val + " ");
        if(cur.left != null){
            queue.offer(cur.left);
        }
        if(cur.right != null){
            queue.offer(cur.right);
        }
    }
}

第二种方法:队列 + 二维数组 

也就是力扣链接里的题目,它主要是让我们把每一层的数据放在一起,这里我们可以通过定义一个size变量,来记录每一层数据的个数。

public List<List<Integer>> levelOrder2(TreeNode root) {
    List<List<Integer>> ret = new ArrayList<>();
    if (root == null) {
        return ret;
    }


    Queue<TreeNode> queue = new LinkedList<>();
    queue.offer(root);

    while (!queue.isEmpty()) {
        int size = queue.size();
        List<Integer> list = new ArrayList<>();
        while (size != 0) {
            TreeNode cur = queue.poll();
            list.add(cur.val);
            //System.out.print(cur.val + " ");
            if (cur.left != null) {
                queue.offer(cur.left);
            }
            if (cur.right != null) {
                queue.offer(cur.right);
            }
            size--;
        }
        ret.add(list);
    }
    return ret;
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

imo云办公室 Imo_DownLoadUI.php 任意文件下载漏洞复现

0x01 漏洞描述&#xff1a; imo云办公室由上海易睦网络科技有限公司于2007年创立&#xff0c;总部位于上海&#xff0c;imo云办公室管理运营企业即时通讯平台imo&#xff0c;包括对imo的在线支持&#xff0c;故障处理&#xff0c;客户服务等&#xff0c;对imo进行持续研发&…

第五届“马栏山杯”国际音视频算法大赛创新应用赛投票环节正式启动啦!

本次大赛分为专业奖和大众人气奖。专业奖由评委直接选出。大众人气奖经组委会初筛后选出62组优秀作品&#xff0c;由网络投票选出40名获奖选手&#xff01; 快快戳链接&#x1f517;&#xff1a;https://h5.shuziwenbo.cn/challenge/vote?cxidedcrfv看看自己的作品有没有入选吧…

【AI视频】Runway Gen-2:图文生视频与运动模式详解

博客主页&#xff1a; [小ᶻZ࿆] 本文专栏: AI视频 | Runway 文章目录 &#x1f4af;前言&#x1f4af;仅图片生成视频方法一&#xff1a;通过Midjourney生成图片方法二&#xff1a;通过Runway预览生成图片注意点 &#x1f4af;图加文生成视频方式一&#xff1a;Midjourney…

Web端云剪辑解决方案,BS架构私有化部署,安全可控

传统视频制作流程繁琐、耗时&#xff0c;且对专业设备和软件的高度依赖&#xff0c;常常让企业望而却步&#xff0c;美摄科技凭借其强大的技术实力和创新能力&#xff0c;推出了面向企业用户的Web端云剪辑解决方案&#xff0c;为企业提供一站式、高效、便捷的视频生产平台。 B…

计算机考研408-计算机网络

【题33】下列选项中&#xff0c;不属于网络体系结构所描述的内容是&#xff08;&#xff09; A.网络的层次 B.每一层使用的协议 C.协议的内部实现细节 D.每一层必须完成的功能 解析&#xff1a; 本题考查的是网络体系结构相关的概念。 图1描述了网络的7层架构以及每一层所要完成…

无人机 PX4 飞控 | EKF 使用传感器汇总与添加传感器方法

无人机 PX4 飞控 | EKF 使用传感器汇总与添加传感器方法 前言飞控自带基本传感器IMU磁力计气压计静态气压位置误差校正气压计偏压补偿 高度传感器测距仪使能测距仪融合有条件 可额外配置的传感器光流外部视觉系统 新传感器确定传感器类型和接口更新硬件定义添加驱动更新EKF 前言…

MySQL:事务的ACID特性隔离级别脏读、不可重复读、幻读、Next-Key锁——场景复现

目录 1、什么是事务 2、 事务的ACID特性 2.1 事务的隔离性 3、为什么要使用事务&#xff1f; 4、查看支持事务的存储引擎 5、使用事务 5.1 控制事务 5.1.1 开启事务 5.1.2 关闭事务 5.2 开始一个事务&#xff0c;执行修改后回滚 5.3 开始一个事务&#xff0c;执行修…

观后感:《中国数据库前世今生》——时代变迁中的数据库崛起

最近观看了《中国数据库前世今生》纪录片&#xff0c;这部影片详细梳理了从1980年代至今&#xff0c;中国数据库技术发展的跌宕历程。作为一名程序员&#xff0c;这部纪录片让我不禁感慨数据库技术的飞速进步&#xff0c;也让我更深入地理解了数据库技术在我们日常生活中的重要…

如何借助项目管理系统实现审批流程的自动化与标准化?

在快节奏的项目申报领域中&#xff0c;繁琐的审批流程往往成为制约项目推进速度的瓶颈。传统的人工审批方式不仅耗时耗力&#xff0c;还容易因人为因素导致审批效率低下、结果不一致等问题。为此&#xff0c;一款能够支持在线审批流程、实现审批自动化与标准化的项目管理系统显…

Canal+RabbitMQ数据同步环境配置

Canal 是阿里巴巴开发的开源工具&#xff0c;主要用于解析 MySQL 的 binlog 日志&#xff0c;从而实现数据同步。Canal 会模拟 MySQL 从库的协议&#xff0c;订阅主库的 binlog&#xff0c;从而获取数据库的变更信息。 将 Canal 解析到的 MySQL 数据库变更消息通过 RabbitMQ 分…

算法打卡 Day34(贪心算法)-分发饼干 + 摆动序列 + 最大子序和

文章目录 理论基础Leetcode 455-分发饼干题目描述解题思路类似题目2410-运动员和训练师的最大匹配数 Leetcode 376-摆动序列题目描述解题思路 Leetcode 53-最大子序和题目描述解题思路 理论基础 贪心算法的本质是选择每一阶段的局部最优&#xff0c;从而达到全局最优。 贪心算…

力扣718-最长重复子数组(Java详细题解)

题目链接&#xff1a;718. 最长重复子数组 - 力扣&#xff08;LeetCode&#xff09; 前情提要&#xff1a; 因为本人最近都来刷dp类的题目所以该题就默认用dp方法来做。 dp五部曲。 1.确定dp数组和i下标的含义。 2.确定递推公式。 3.dp初始化。 4.确定dp的遍历顺序。 5…

【CMake】使用CMake在Visual Studio内构建多文件夹工程

一、配置准备 打开VIsual Studio&#xff0c;载入写好的 C M a k e l i s t s . t x t CMakelists.txt CMakelists.txt&#xff0c;在项目中添加以下文件&#xff1a; 创建一个文件夹 f u n c s funcs funcs&#xff0c;里面放入 f u n c . h func.h func.h、 f u n c . c p …

fmql之驱动程序编写(首次)

看了正点原子的zynq系列的Linux开发指南&#xff08;pdf和视频均有&#xff09;&#xff0c;因此从最简单的程序开始。 驱动程序开发&#xff1a;&#xff08;第四期视频&#xff09; 第3.1讲 我的第一个Linux驱动-字符设备驱动框架_哔哩哔哩_bilibili 学习驱动程序编写之前&am…

【论文串烧】多媒体推荐中的模态平衡学习 | 音视频语音识别中丢失导致的模态偏差对丢失视频帧鲁棒性的影响

文章目录 一、多媒体推荐中的模态平衡学习1.1 研究背景1.2 解决问题1.3 实施方案1.4 文章摘要1.5 文章重点1.6 文章图示图 1&#xff1a;不同模型变体在 AmazonClothing 数据集上的初步研究图 2&#xff1a;CKD模型架构的说明图 3&#xff1a;在 Amazon-Clothing 数据集上训练过…

【Linux:共享内存】

共享内存的概念&#xff1a; 操作系统通过页表将共享内存的起始虚拟地址映射到当前进程的地址空间中共享内存是由需要通信的双方进程之一来创建但该资源并不属于创建它的进程&#xff0c;而属于操作系统 共享内存可以在系统中存在多份&#xff0c;供不同个数&#xff0c;不同进…

Qt窗口——QStatusBar

文章目录 状态栏状态栏创建状态栏显示临时消息状态栏添加子控件 状态栏 QStatusBar状态栏是应用程序中输出简要信息的区域&#xff0c;例如画图板下面的区域 我们也可以给程序设置状态栏&#xff0c;表示一些状态。 状态栏创建 使用Qt Creator创建项目的时候&#xff0c;如果…

实现一种可插拔的参数校验

1、概述 仿照mybatis的二级缓存的实现方式&#xff0c;使用“策略模式配置” 的方式实现一个可动态插拔的 参数校验&#xff0c;便于后期扩展。 实现方式也很简单&#xff0c;首先定义一个校验接口&#xff0c;并提供一个校验方法&#xff1b;每种参数校验都是实现 了该校验接口…

前端vue-实现富文本组件

1.使用wangeditor富文本编辑器 工具网站&#xff1a;https://www.wangeditor.com/v4/ 下载安装命令&#xff1a;npm i wangeditor --save 成品如下图&#xff1a; 组件实现代码 <template><div><!-- 富文本编辑器 --><div id"wangeditor">…

Recbole安装指南:步骤详解与常见问题解决方案

1.两种方式&#xff1a; 从Conda安装 如果你还没有安装Conda&#xff0c;可以安装Miniconda或完整的Anaconda。 如果你在中国大陆&#xff0c;我们推荐你使用清华镜像安装Conda。 当你完成Conda的安装后&#xff0c;你可以将RecBole安装在python 3.7的Conda环境中&#xff0…