数据结构:二叉树(2)

二叉树的基本操作

获取树的结点总数

遍历思路:

每次遍历一个节点,遍历完nodeSize++,然后遍历它的左右子树

如果遍历到空的节点,就返回0

    public int nodeSize = 0;int size(TreeNode root){if(root == null){return 0;}nodeSize++;size(root.left);size(root.right);return nodeSize;}

子树相加思路

整棵树的节点个数 = 左子树的节点个数+右子树的节点个数 + 根节点

    int size2(TreeNode root){if(root == null){return 0;}return size2(root.left) + size2(root.right) + 1;}

size2(root.left) 可以理解为左子树所有节点的总数

size2(root.right)可以理解为右子树所有节点的总数


计算二叉树叶结点的总数

遍历思路:遍历结点和左右子树,如果遍历到有一个结点左右子树都为null,那么这个结点就是叶结点,计数器++

    // 获取叶子节点的个数//遍历思路public int leafNode = 0;int getLeafNodeCount(TreeNode root){if(root == null){return 0;}if(root.left == null && root.right == null){leafNode++;}getLeafNodeCount(root.left);getLeafNodeCount(root.right);return leafNode;}

子树相加思路:整棵树叶子 = 左子树叶子 + 右子树叶子

    //子树相加思路int getLeafNodeCount2(TreeNode root) {if (root == null) {return 0;}if (root.left == null && root.right == null) {return 1;}return getLeafNodeCount2(root.left) + getLeafNodeCount2(root.right);}

获取第k层的结点个数

思路:

整棵树第k层节点数 = 左子树第k-1层结点数+右子树第k-1层结点数

感觉有杨辉三角的感觉(bushi

    // 获取第K层节点的个数public int nodeCount = 0;int getKLevelNodeCount(TreeNode root,int k){if(root == null){return 0;}if(k == 1){return 1;}return getKLevelNodeCount(root.left,k-1) + getKLevelNodeCount(root.right,k-1);}

 求二叉树的高度

高度就是最大层数,整棵树的高度 = 左子树的高度和右子树的高度的最大值+1

A的左子树是B,右子树是C

那B的高度怎么求呢?很简单,再递归一下呗,把B当成根结点,左子树B高度就等于B的左子树和右子树高度最大值+1

这样递归递归就能求出左子树总高度了,右子树也同理

    int getHeight(TreeNode root){if(root == null){return 0;}int leftHeight = getHeight(root.left);int rightHeight = getHeight(root.right);return leftHeight > rightHeight ? leftHeight + 1 : rightHeight + 1;}

换种写法

    int getHeight2(TreeNode root){if(root == null){return 0;}return getHeight2(root.left) > getHeight2(root.right) ? getHeight2(root.left) + 1 : getHeight2(root.right) + 1;}

第二种写法放编译器可以跑,但是放到力扣跑不了

104. 二叉树的最大深度 - 力扣(LeetCode)

它会报这么一个错误

原因就是return的时候好不容易递归完判断左右子树大小,还得再重复递归一次计算总高度,所以跑太久力扣就给你报超时的错误了


检测特定值的元素是否存在

这个直接用前序遍历就行了

    TreeNode find(TreeNode root, int val){if(root == null){return null;}//判断根结点是不是if(root.val == val){return root;}TreeNode ret = find(root.left, val);if(ret != null){return ret;//这样就不用去右边了}TreeNode ret2 = find(root.right,val);if(ret2 != null){return ret2;}return null;}

二叉树面试题

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

给你两棵二叉树的根节点 p 和 q ,编写一个函数来检验这两棵树是否相同。

如果两个树在结构上相同,并且节点具有相同的值,则认为它们是相同的。

示例 1:

输入:p = [1,2,3], q = [1,2,3]
输出:true

示例 2:

输入:p = [1,2], q = [1,null,2]
输出:false

示例 3:

输入:p = [1,2,1], q = [1,1,2]
输出:false

提示:

  • 两棵树上的节点数目都在范围 [0, 100] 内
  • -104 <= Node.val <= 104

1.如果两个结点都不为空,就判断值

2.如果一个结点为空一个结点不为空,那必不一样

总结:判断根及其左子树和右子树是否相同

class Solution {public boolean isSameTree(TreeNode p, TreeNode 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);}
}


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

给你两棵二叉树 root 和 subRoot 。检验 root 中是否包含和 subRoot 具有相同结构和节点值的子树。如果存在,返回 true ;否则,返回 false 。

二叉树 tree 的一棵子树包括 tree 的某个节点和这个节点的所有后代节点。tree 也可以看做它自身的一棵子树。

示例 1:

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

示例 2:

输入:root = [3,4,5,1,2,null,null,null,null,0], subRoot = [4,1,2]
输出:false

提示:

  • root 树上的节点数量范围是 [1, 2000]
  • subRoot 树上的节点数量范围是 [1, 1000]
  • -104 <= root.val <= 104
  • -104 <= subRoot.val <= 104

1.注意:如果是子树,有可能是两棵相同的树,那可以先比较根结点

2.如果根结点比较完发现不是两棵相同的树,那么subRoot这棵树和root的某一棵子树是相同的

3.判断subRoot和root的左子树是不是相同的,不是就判断右子树。都不是就false了

刚刚那个isSameTree()方法不久能用上了吗

    public boolean isSameTree(TreeNode p, TreeNode 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);}public boolean isSubtree(TreeNode root, TreeNode subRoot) {if(isSameTree(root,subRoot)){return true;}if(isSubtree(root.left,subRoot)){return true;}if(isSubtree(root.right,subRoot)){return true;}return false;}

 欸但是力扣直接给我报了一个空指针异常

这是因为假如root的左子树就是空的,root第一个if判断完之后进入左子树变成空,空指针进不了第二个if判断,所以跳过直接进入到右子树的if判断,那此时root都为空了,系统自然就报了一个空指针异常了

🆗其实我们在判断根结点是否相同前先判断会不会有空就行了

        if(root == null || subRoot == null){return false;}

 


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

给你一棵二叉树的根节点 root ,翻转这棵二叉树,并返回其根节点。

示例 1:

输入:root = [4,2,7,1,3,6,9]
输出:[4,7,2,9,6,3,1]

示例 2:

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

示例 3:

输入:root = []
输出:[]

提示:

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

相当于我们进行数组交换一样 

每次遍历到一个结点,就把这个结点的两个引用都换一下就好了

直到所有结点都遍历完成

class Solution {public TreeNode invertTree(TreeNode root) {if(root == null){return null;}if(root.left == null && root.right == null){return root;}TreeNode tmp = root.left;root.left = root.right;root.right = tmp;//递归搞左右树invertTree(root.left);invertTree(root.right);return root;}
}


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

给定一个二叉树,判断它是否是高度平衡的二叉树。

本题中,一棵高度平衡二叉树定义为:

一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1 。

示例 1:

输入:root = [3,9,20,null,null,15,7]
输出:true

示例 2:

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

示例 3:

输入:root = []
输出:true

提示:

  • 树中的节点数在范围 [0, 5000] 内
  • -104 <= Node.val <= 104

思路:

1.判断当前根结点的左子树高度-右子树高度的绝对值是否<=1

2.根的左子树是平衡的并且右子树也得是平衡的

这道题高度方法前面已经写完了,直接调用就行(getHeight())

class Solution {public int getHeight(TreeNode root){if(root == null){return 0;}int leftHeight = getHeight(root.left);int rightHeight = getHeight(root.right);return leftHeight > rightHeight ? leftHeight + 1 : rightHeight + 1;}public boolean isBalanced(TreeNode root) {if(root == null){return true;}//分别求左右树高度int leftHeight = getHeight(root.left);int rightHeight = getHeight(root.right);//判断绝对差值<=1并且左右子树都平衡return Math.abs(leftHeight-rightHeight) <= 1 && isBalanced(root.left) && isBalanced(root.right);}
}

这里的时间复杂度是O(N^2),在求左子树和右子树高度调用getHeight时间复杂度已经是O(N)了,return部分再调用isBalance,相当于又遍历了一遍所有的n个结点,isBalance嵌套了getHeight,时间复杂度就是n*n了

进阶难度:使用O(N)的时间复杂度来计算

我们在求子树高度的时候,返回高度时直接让他们进行比较,如果>1就返回-1给根结点

class Solution {public int getHeight(TreeNode root){if(root == null){return 0;}int leftHeight = getHeight(root.left);int rightHeight = getHeight(root.right);if(leftHeight >= 0 && rightHeight>=0&& Math.abs(leftHeight - rightHeight)<=1){//返回真实高度return Math.max(leftHeight,rightHeight)+1;}else{return -1;}}public boolean isBalanced(TreeNode root) {if(root == null){return true;}int leftHeight = getHeight(root.left);int rightHeight = getHeight(root.right);return getHeight(root) >= 0;}
}

达到O(n)的时间复杂度 


101. 对称二叉树 - 力扣(LeetCode)

给你一个二叉树的根节点 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.一个为空另一个不为空

2.值不一样

3.左树的左和右树的左对称?左树的右和右树的左对称?

注意:left和right都为空就是对称

    public boolean isSymmetric(TreeNode root) {if(root == null){return true;}return isSymmetricChild(root.left,root.right);}private boolean isSymmetricChild(TreeNode leftTree, TreeNode rightTree){if((leftTree != null && rightTree == null) || (leftTree == null && rightTree != null)){return false;}if(leftTree == null && rightTree == null){return true;}if(leftTree.val != rightTree.val){return false;}return isSymmetricChild(leftTree.left,rightTree.right) && isSymmetricChild(leftTree.right,rightTree.left);}

二叉树遍历_牛客题霸_牛客网 (nowcoder.com)

描述

编一个程序,读入用户输入的一串先序遍历字符串,根据此字符串建立一个二叉树(以指针方式存储)。 例如如下的先序遍历字符串: ABC##DE#G##F### 其中“#”表示的是空格,空格字符代表空树。建立起此二叉树以后,再对二叉树进行中序遍历,输出遍历结果。

输入描述:

输入包括1行字符串,长度不超过100。

输出描述:

可能有多组测试数据,对于每组数据, 输出将输入字符串建立二叉树后中序遍历的序列,每个字符后面都有一个空格。 每个输出结果占一行。

示例1

输入:

abc##de#g##f###

输出:

c b e g d f a 

 思路:遍历这个字符串,根据前序遍历来创建二叉树,最后再用中序遍历这棵树

    public static int i = 0;public static void main(String[] args) {Scanner in = new Scanner(System.in);// 注意 hasNext 和 hasNextLine 的区别while (in.hasNextLine()) { // 注意 while 处理多个 caseString str = in.nextLine();TreeNode root = createTree(str);inorder(root);}}public static TreeNode createTree(String str){TreeNode root = null;//遍历字符串strif(str.charAt(i) != '#'){root = new TreeNode(str.charAt(i));i++;//根据前序遍历创建二叉树root.left = createTree(str);root.right = createTree(str);}else{i++;}//返回root之后才会继续调用createTree来创建左右子树return root;}public static void inorder(TreeNode root){if(root == null){return ;}inorder(root.left);System.out.print(root.val+" ");inorder(root.right);}

被static修饰的成员变量只有一份,它是和很多对象共享的

因为本题只有一个测试用例,所以i可以被static修饰。如果有两个测试用例,第一个测试用例执行完假设i停在5的位置,第二个测试用例就只能从5位置开始创建二叉树了

所以后面static成员变量在oj里面要慎用

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

LeetCode讲解篇之77. 组合

文章目录 题目描述题解思路题解代码 题目描述 题解思路 遍历nums&#xff0c;让当前数字添加到结果前缀中&#xff0c;递归调用&#xff0c;直到前缀的长度为k&#xff0c;然后将前缀添加到结果集 题解代码 func combine(n int, k int) [][]int {var nums make([]int, n)fo…

【MATLAB源码-第51期】基于matlab的粒子群算法(PSO)的栅格地图路径规划。

操作环境&#xff1a; MATLAB 2022a 1、算法描述 粒子群算法&#xff08;Particle Swarm Optimization&#xff0c;简称PSO&#xff09;是一种模拟鸟群觅食行为的启发式优化方法。以下是其详细描述&#xff1a; 基本思想&#xff1a; 鸟群在寻找食物时&#xff0c;每只鸟都会…

arrow(c++)改写empyrical系列1---用arrow读取基金净值数据并计算夏普率

用arrow c版本读取了csv中的基金净值数据&#xff0c;然后计算了夏普率&#xff0c;比较尴尬的是&#xff0c;arrow c版本计算耗费的时间却比python的empyrical版本耗费时间多。。。 arrow新手上路&#xff0c;第一次自己去实现功能&#xff0c;实现的大概率并不是最高效的方…

windows上下载github上的linux内核项目遇到的问题

问题一&#xff1a;clone的时候报错 Cloning into G:\github\linux... POST git-upload-pack (gzip 27925 to 14032 bytes) remote: Counting objects: 6012062, done. remote: Compressing objects: 100% (1031/1031), done. remote: Total 6012062 (delta 893), reused 342 (…

【Axure高保真原型】可视化图表图标

今天和粉丝们免费分享可视化图表图标原型模板&#xff0c;包括柱状图、条形图、环形图、散点图、水波图等常用的可视化图表图标。 【原型效果】 【原型预览】 https://axhub.im/ax9/d402c647c82f9185/#c1 【原型下载】 这个模板可以在 Axure高保真原型哦 小程序里免费下载哦…

0基础学习VR全景平台篇第110篇:源图像导入和镜头预设 - PTGui Pro教程

上课&#xff01;全体起立~ 大家好&#xff0c;欢迎观看蛙色官方系列全景摄影课程&#xff01; 本节教程&#xff0c;我们讲述拼接软件 PTGui Pro 操作的第一步&#xff1a;导入源图像和预设镜头&画幅参数。 我们此次课堂有两个重点&#xff1a; 第一点是 培养摄影后期…

HTTPS、SSL/TLS,HTTPS运行过程,RSA加密算法,AES加密算法

1、为什么网站要使用安全证书 我们所处的网络环境是复杂多样的&#xff0c;大致分为两类&#xff0c;一类是可信的网络服务商&#xff0c;比如直接连的电信运营商的网络&#xff0c;网线&#xff0c;4G&#xff0c;5G&#xff1b;另一类是不可信的网络&#xff0c;比如WIFI&am…

会声会影2024有哪些新功能?好不好用

比如会声会影视频编辑软件&#xff0c;既加入光影、动态特效的滤镜效果&#xff0c;也提供了与色彩调整相关的LUT配置文件滤镜&#xff0c;可选择性大&#xff0c;运用起来更显灵活。会声会影在用户的陪伴下走过20余载&#xff0c;经过上百个版本的优化迭代&#xff0c;已将操作…

ubuntu20.04 nvidia显卡驱动掉了,变成开源驱动,在软件与更新里选择专有驱动,下载出错,调整ubuntu镜像源之后成功修复

驱动配置好&#xff0c;环境隔了一段时间&#xff0c;打开Ubuntu发现装好的驱动又掉了&#xff0c;软件与更新 那里&#xff0c;附加驱动&#xff0c;显示开源驱动&#xff0c;命令行输入 nvidia-smi 命令查找不到驱动。 点击上面的 nvidia-driver-470&#xff08;专有&#x…

Maven 生命周期clean default size含义

clean 负责清理工作&#xff0c;清理上一次项目构建产生的一些文件&#xff0c;如编译后的字节码文件&#xff0c;打包后的jar包文件 default 整一个项目构建的核心工作&#xff0c;如编译&#xff0c;测试&#xff0c;打包&#xff0c;安装&#xff0c;部署等等 size 生成报告…

【Mysql】B+树索引的使用(七)

前言 每个索引都对应一棵 B 树&#xff0c; B 树分为多层&#xff0c;最下边一层是叶子节点&#xff0c;其余的是内节点&#xff08;非叶子节点&#xff09;。所有用户记录都存储在 B 树的叶子节点&#xff0c;所有目录项记录都存储在内节点。 InnoDB 存储引擎会自动为主键&am…

实现Linux下Word转PDF、Java调用命令方式

使用 LibreOffice 实现 Word 转 PDF 和 Java 调用命令 1、 安装 LibreOffice 外网安装 # 一键安装 yum install -y libreoffice # 验证版本 libreoffice --version # Warning: -version is deprecated. Use --version instead. # LibreOffice 7.5.6.2 f654817fb68d6d4600d7…

数据仓库扫盲系列(1):数据仓库诞生原因、基本特点、和数据库的区别

数据仓库的诞生原因 随着互联网的普及&#xff0c;信息技术已经深入到各行各业&#xff0c;并逐步融入到企业的日常运营中。然而&#xff0c;当前企业在信息化建设过程中遇到了一些困境与挑战。 1、历史数据积存。 过去企业的业务系统往往是在较长时间内建设的&#xff0c;很…

MODBUS-TCP转MODBUS-RTU通信应用(S7-1200和串口服务器通信)

在学习本博客之前,大家需要熟悉MODBUS-TCP和MODBUS-RTU通信,这2个通信的编程应用,大家可以查看下面文章链接: MODBUS-RTU通信 MODBUS-RTU通信协议功能码+数据帧解读(博途PLC梯形图代码)-CSDN博客MODBUS通信详细代码编写,请查看下面相关链接,这篇博客主要和大家介绍MODB…

Rust逆向学习 (1)

文章目录 Hello, Rust Reverse0x01. main函数定位0x02. main函数分析line 1line 2line 3line 4~9 0x03. IDA反汇编0x04. 总结 近年来&#xff0c;Rust语言的热度越来越高&#xff0c;很多人都对Rust优雅的代码和优秀的安全性赞不绝口。对于开发是如此&#xff0c;对于CTF也是如…

Easyx趣味编程7,鼠标消息读取及音频播放

hello大家好&#xff0c;这里是dark flame master&#xff0c;今天给大家带来Easyx图形库最后一节功能实现的介绍&#xff0c;前边介绍了绘制各种图形及键盘交互&#xff0c;文字&#xff0c;图片等操作&#xff0c;今天就可以使写出的程序更加生动且容易操控。一起学习吧&…

【CSS】使用 CSS 实现一个宽高自适应的正方形

1. 利用 padding 或 vw <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><metaname"viewport"content"widthdevice-width, initial-scale1.0"><title>Document</title><st…

YOLOv5改进实战 | GSConv + SlimNeck双剑合璧,进一步提升YOLO!

前言 轻量化网络设计是一种针对移动设备等资源受限环境的深度学习模型设计方法。下面是一些常见的轻量化网络设计方法: 网络剪枝:移除神经网络中冗余的连接和参数,以达到模型压缩和加速的目的。分组卷积:将卷积操作分解为若干个较小的卷积操作,并将它们分别作用于输入的不…

【驱动开发】控制stm32mp157a开发板三盏灯的亮灭

编写应用程序控制三盏灯的亮灭 head.h&#xff1a; #ifndef __HEAD_H__ #define __HEAD_H__typedef struct {unsigned int MODER;unsigned int OTYPER;unsigned int OSPEEDR;unsigned int PUPDR;unsigned int IDR;unsigned int ODR; }gpio_t;//LED灯的寄存器地址 #define …

制造企业如何做好MES管理系统需求分析

随着制造业的不断发展&#xff0c;制造企业对于生产过程的管理需求日益增长。为了提高生产效率和质量&#xff0c;越来越多的制造企业开始关注MES生产管理系统的需求分析。本文将从以下几个方面探讨制造企业如何做好MES管理系统需求分析。 一、明确需求 在进行MES管理系统需求…