二叉树练习习题集一(Java)

1.

b38f51b0a202428da67f0bcb480f177e.png

思路:

就是让左孩子和右孩子进行交换,这里需要一个中间变量用来记录,然后完成交换。如果进行优化则添加当左孩子和右孩子都为null时直接返回。

class Solution {public TreeNode invertTree(TreeNode root) {TreeNode tmp=null;//用来进行交换的中间变量if(root==null){return null;}if(root.left==null&&root.right==null){//如果是叶子结点return root;}//将该结点的左右孩子进行交换tmp=root.left;root.left=root.right;root.right=tmp;//交换完后,继续交换左孩子和右孩子的下一代invertTree(root.left);invertTree(root.right);return root;//返回根结点}
}

2.

148dd916c81b45cb8742f6e42e9f4721.png

思路:

判断两颗树是不是相同的树,一共有两个方面需要判断,一个是结构是否相同,一个是值是否相同,在结构上,我们判断两棵树相同位置是否存在相同的结点,一共有四种情况:

1.两个结点都为空

2.两个结点都不为空

3.A树的结点为空,B树的结点不为空

4.A树的结点不为空,B树的结点为空

其中3,4的情况都可以判断出这两棵树是不相同的,所以可以直接返回false

1可以判断相同,因为为空,所以值也不用进行判断,2的情况下,判断了结构是相同的,但还要继续判断值是否一样,如果值不一样,也返回false,如果值也一样,说明该位置的结点是一样的,接下来判断左右子树,如此类推

class Solution {public boolean isSameTree(TreeNode p, TreeNode q) {//如果两个结点都为空if(p==null&&q==null){return true;}//如果两个结点都不为空if(p!=null&&q!=null){if(p.val==q.val){//如果两个结点值为一样return isSameTree(p.left,q.left)&&isSameTree(p.right,q.right);//继续判断左右子树是否一样}else{//如果两个结点值为不一样return false;}}//如果其中一个结点为空,另一个结点不为空return false;}
}

3.

ae7cafff599f45caa6cb30d1fd5bfe47.png

思路:

判断根结点的左右子树是否对称,主要看两个方面,一个是结构,然后是值,这跟上面那道判断是否是相同树的题类似,只不过传参的时候,一个传左子树的左孩子和右子树的右孩子,一个传左子树的右孩子和右子树的左孩子

class Solution {public boolean isSameNode(TreeNode leftTree,TreeNode rightTree){//两个都为空if(leftTree==rightTree&&leftTree==null){return true;}//其中一个为空,另外一个不为空if(leftTree==null&&rightTree!=null||leftTree!=null&&rightTree==null){return false;}//两个都不为空但是值不一样if(leftTree.val!=rightTree.val){return false;}//两个都不为空且值一样return isSameNode(leftTree.left,rightTree.right)&&isSameNode(leftTree.right,rightTree.left);}public boolean isSymmetric(TreeNode root) {//如果是空树if(root==null){return true;}//判断左右子树是否对称return isSameNode(root.left,root.right);}
}

4.

471ba647cfa3436d8ecb42252d880bda.png

思路:

平衡二叉树就是每一个结点的左右子树的高度都相差小于等于1,所以只需要遍历每个结点,然后求出每个结点左右子树的高度,进行判断高度是否相差小于等于1即可

class Solution {public boolean isBalanced(TreeNode root) {if(root==null){//如果结点为空return true;}int left=getHeight(root.left);//求左树高度int right=getHeight(root.right);//求右树高度if(Math.abs(left-right)>1){//如果不是平衡二叉树return false;}else{//继续遍历左右结点return isBalanced(root.left)&&isBalanced(root.right);}}public int getHeight(TreeNode node){if(node==null){//结点为空return 0;//高度为0}int left=getHeight(node.left);//左子树高度int right=getHeight(node.right);//右子树高度return (left>right?left:right)+1;//高的子树的高度加1}
}

但是这样子效率很低,首先要遍历所有结点,并且每个结点求高度又要遍历该结点的所有子结点,时间复杂度达到了O(n^2),因此虽然思路简单,但是效率不高。

字节面试就曾问过,在时间复杂度不超过O(n)的情况下,完成本题

原来求一个结点高度时,就已经从叶子结点开始往上递归求得高度,然后又遍历子结点,又要从叶子结点又往上递归求高度,有许多重复的计算,也是为什么第一种代码效率低下的原因

所以关键点就是要优化这里,如何求高度的同时就判断出是否是平衡二叉树?这时就可以发现,我们求高度的方法是求出左右子树的高度,然后高的子树的高度加1,那么此时我们已经得到了左右子树的高度,只需要判断一下高度相差是否超过1即可,这样子就可以在求高度的同时,判断出下面的结点是否是平衡二叉树

class Solution {public boolean isBalanced(TreeNode root) {if(root==null){return true;}int left=getHeight(root.left);int right=getHeight(root.right);//如果有-1,说明左右子树不是平衡二叉树,或者根结点的左右子树高度相差超过1if(left<0||right<0||Math.abs(left-right)>1){return false;}else{return true;}}public int getHeight(TreeNode node){if(node==null){return 0;}int left=getHeight(node.left);int right=getHeight(node.right);if(left<0||right<0||Math.abs(left-right)>1){//如果发现不是平衡二叉树return -1;//返回-1作为标记}else{return (left>right?left:right)+1;//正常求高度}}
}

 5.

70f3bca520654d6e8dd5eedcd6da8c07.png

思路:

前提知识:二叉搜索树有一个特性,就是左边子结点的值一定比父结点的值小,右边子结点的值一定比父结点的大,根据这个特性,如果使用中序遍历的话,那么就将是一个有序的从小到大的排列

根据题目描述,left作为前驱,right作为后继

当我们继续中序遍历时,最先到的是4

这时我们需要一个prev结点用来记录前一个结点的位置,此时prev初始化为null

4的left指向prev,prev记录为4,此时4的后继是6,但是现在拿不到6,所以先暂时如此

然后递归回退到6,6的left指向prev,prev记录为6,但是在这两步之间,应该让prev的right指向6,形成双向链表

但是在4时,prev还为null,所以这时候需要特殊判断一下

这样就将二叉树通过中序遍历,变成了一条有序的双向链表

这时候只需要定义一个结点head,循环当head.left != null,head=head.left,最后跳出循环就能找到4这个结点

返回head即可

public class Solution {public TreeNode Convert(TreeNode pRootOfTree) {if(pRootOfTree==null){//如果为空树return null;}Convertchild(pRootOfTree);//将二叉树变为双向链表TreeNode head=pRootOfTree;//定义一个头结点while(head.left!=null){//一直找到最左下角的结点head=head.left;}return head;//此时head就是中序遍历到的第一个结点}TreeNode prev=null;//用来记录前一个结点public void Convertchild(TreeNode root){//使二叉搜索树变为双向链表if(root==null){return;}Convertchild(root.left);//先左//进行转化root.left=prev;//left指向前一个结点if(prev!=null){//除了一开始时prev.right=root;//前面的结点的right指向当前结点        }prev=root;//记录当前结点为prevConvertchild(root.right);//后右}
}

6.

0ac5842cc66b4c438052f4482730695f.png

思路:

首先是有多组数据,所以要用hasnextLine()来读取,然后用一个变量i来遍历字符串,同时定义一个返回值为树结点的方法叫creatTree,在这个方法里,定义一个树结点初始为null,如果i对应的字符不是#,则创建对应字符的结点,i往后走一位,然后让该结点的左孩子等于创建左树,让该结点的右孩子创建右树。如果等于#,则什么也不做,i往后走一位。最后的返回值都为创建的新结点

因为每次遍历中,i的值都保留原来的位置,所以i得是全局静态变量,又因为有可能有多组数据,所以每次处理完一组数据后,i要重新赋值为0,为下一组数据做准备

import java.util.Scanner;class TreeNode{//定义树的类public char val;public TreeNode left;public TreeNode right;TreeNode(char val){//构造方法this.val=val;}
}
// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {public static void main(String[] args) {Scanner in=new Scanner(System.in);while(in.hasNextLine()){//多组数据String str=in.nextLine();TreeNode root=CreatTree(str);inorderTree(root);//中序打印i=0;//清零,为下一组数据作准备System.out.println();//打印完一组数据换行}}public static int i=0;public static TreeNode CreatTree(String str){TreeNode root=null;//如果是#就直接返回nullif(str.charAt(i)!='#'){root=new TreeNode(str.charAt(i));//创建结点i++;root.left=CreatTree(str);//创建左树root.right=CreatTree(str);//创建右树}else{i++;}return root;}public static void inorderTree(TreeNode root){if(root==null){return;}inorderTree(root.left);//先左System.out.print(root.val+" ");//打印inorderTree(root.right);//后右}
}

 

 

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

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

相关文章

网络原理知识总结

一、网络模型 1.1 osi七层参考模型 物理层&#xff1a;连接通信链路、传输比特流数据链路层&#xff1a;数据封装成帧&#xff0c;在节点与节点间实现可靠物理地址寻址&#xff0c;进行差错校验、流量控制网络层&#xff1a;逻辑地址寻址&#xff0c;路由选择 IP(IPV4IPV6) I…

window.onload、$(document).ready()、Vue.created() 页面加载完成后执行方法

1、JavaScript 的 window.onload 方法 window.onload 方法是在页面所有元素&#xff08;包括图片、样式、链接等&#xff09;加载完成后触发的&#xff0c;在这个事件之前&#xff0c;页面上的所有资源都必须加载完成。因此&#xff0c;如果页面中包含大量的图片或其他资源&am…

【iOS】——响应者链和事件传递链

事件传递 事件传递流程 发生触摸事件后&#xff0c;系统会将该事件封装成UIEvent对象加入到一个由UIApplication管理的事件队列 UIApplication会从事件队列中取出最前面的事件&#xff0c;并将事件分发下去以便处理&#xff0c;通常&#xff0c;先发送事件给应用程序的主窗口…

TCP详解(一)报文详情/MSS/MTU

本文旨在介绍TCP的报文格式详情和传输层、链路层的字节数限制 1 TCP 协议的报文格式 TCP 报文段包括协议首部和数据两部分&#xff0c;协议首部的固定部分是 20 个字节&#xff0c;头部是固定部分&#xff0c;后面是选项部分。 1.1 端口号 16位源端口&#xff1a;发送方主机…

KDP数据平台:以实战案例验证技术领先力

本文由智领云 LeetTools 工具自动生成 申请试用&#xff1a; https://www.leettools.com/feedback/ 在当今快速发展的技术环境中&#xff0c;数据平台的选择对企业的数字化转型和业务发展至关重要。智领云开源KDP&#xff08;Kubernetes Data Platform&#xff09;在数据处理和…

效果炫酷的3D翻转书特效WordPress主题模板MagicBook主题v1.19

正文&#xff1a; MagicBook是一款支持3D翻书特效的书籍WordPress主题。支持可视化页面搭建&#xff0c;3D菜单&#xff0c;完全自适应设计,WPML多语言支持。 这款主题一定会让你爱不释手。虽然他是英文的&#xff0c;但不可不承认的是&#xff0c;它优雅的设计会让你愿意花时…

无缝融入,即刻智能[二]:Dify-LLM平台(聊天智能助手、AI工作流)快速使用指南,42K+星标见证专属智能方案

无缝融入,即刻智能[二]:Dify-LLM平台(聊天智能助手、AI工作流)快速使用指南,42K+星标见证专属智能方案 1.快速创建应用 你可以通过 3 种方式在 Dify 的工作室内创建应用: 基于应用模板创建(新手推荐) 创建一个空白应用 通过 DSL 文件(本地 / 在线)创建应用 从模板创建…

13 定时器

13 定时器 1、定时1.1 硬件定时器的特性1.2 硬件定时器对应的中断处理函数所作的工作(了解)1.3 linux内核中跟时间相关的三个概念&#xff1a; 2、延时2.1.延时定义2.2 忙等待2.3.休眠等待2.4 等待队列机制2.4.1 介绍2.4.2 结论2.4.3 进程休眠和唤醒的编程步骤方法 1方法 2 3、…

关于uniapp使用izExif.js 插件问题

需求&#xff1a;1.APP获取图片的属性&#xff0c;得到经纬度信息&#xff0c;然后标注到图片上 我们采用izExif.js 插件&#xff0c;进行获取图片信息&#xff0c;在模拟器测试好好地&#xff0c;但是使用真机测试发现getImageData没有返回信息&#xff0c;去izExif.js源码查…

ubuntu中python 改为默认使用python3,pip改为默认使用pip3

一、安装pip和python&#xff08;有的话可跳过&#xff09; 更新软件源 sudo apt update !!!apt和apt-get apt apt-get、apt-cache 和 apt-config 中最常用命令选项的集合。 部分截图为apt-get&#xff0c;建议直接用apt 安装pip和python ubuntu 18.04和更高版本默认安…

字符串金额转换,字符串手机号屏蔽,身份证信息查看,敏感词替换

2135 在发票上面该写成零佰零拾零万贰仟壹佰叁拾伍元 我们用逆推法可以写成零零零贰壹叁伍->贰壹叁伍->2135 1.遍历获取到每一个数字&#xff0c;然后把大写放到数组里面&#xff0c;将数字当作索引&#xff0c;在数组里面查找大写 package stringdemo;import java.uti…

Jakarta Servlet 到 SpringMVC

Jakarta EE&#xff08;曾被称为Java EE&#xff09;是Java平台企业版&#xff08;Java Platform Enterprise Edition&#xff09;的下一代版本&#xff0c;它在Oracle将Java EE的开发和维护交给Eclipse Foundation后得以重生&#xff0c;并更名为Jakarta EE。Jakarta EE保留了…

Windows采用VS2019实现Open3D的C++应用

1、参考链接 https://blog.csdn.net/qq_31254435/article/details/137799739 但是&#xff0c;我的方法和上述链接不大一样&#xff0c;我是采用VS2019进行编译的&#xff0c;方便在Windows平台上验证各种算法。 2、创建一个VS2019的C Console工程 #include <iostream>…

MT1619 (A/B/C/D 15W-25W)快充电源主控芯片

MT1619 是一款快充电源主控芯片&#xff0c;MT1619内部集成了一颗高集成度、高性能的电流模式 PWM 控制器和一颗功率 MOSFET。MT1619适用于小于 30W 的开关电源。MT1619 具有恒功率功能&#xff0c;特别适用于 PD 充电器、电源适配器等中小功率的开关电源设备。极低的启动电流与…

windows下TortoiseSVN切换账号的方法

前言 在项目开始初期的时候大家会使用一个默认账号,后面会根据需要给每个人分配各自的个人账号,这个时候就需要重登陆新的svn账号,下面就是讲解下怎样在windows下修改登录TortoiseSVN的账号。 方法 1.首先在桌面右键&#xff0c;选择TortoiseSVN-settings 2.进入设置页面&a…

阿里云注册、认证、短信资质、签名、模板申请过程

一、帐号注册 输入“帐号密码注册”中的相关信息即可。 手机号是必须的&#xff0c;先确定好手机号。 正常的可以直接注册成功的。 二、实名认证 注册成功之后&#xff0c;就可以点击上述的“快速实名认证”。 这次选择的是“企业认证”。 有几种方式&#xff0c;如下&#x…

clamp靶机复现

靶机设置 设置靶机为NAT模式 靶机IP发现 nmap 192.168.112.0/24 靶机IP为192.168.112.143 目录扫描 dirsearch 192.168.112.143 访问浏览器 提示让我们扫描更多的目录 换个更大的字典&#xff0c;扫出来一个 /nt4stopc/ 目录 目录拼接 拼接 /nt4stopc/ 发现页面中有很多…

CeresPCL 岭回归拟合(曲线拟合)

文章目录 一、简介二、实现代码三、实现效果参考资料一、简介 由于在使用最小二乘插值拟合时,会涉及到矩阵求逆的操作,但是如果这个矩阵接近于奇异时,那么拟合的结果就会与我们期望的结果存在较大差距,因此就有学者提出在最小二乘的误差函数中添加正则项,即: 这里我们也可…

【SpringBoot】SpringBoot框架的整体环境搭建和使用(整合Mybatis,Druid,Junit4,PageHelper,logback等)

目录 1.介绍 1.1 配置文件 1.2 目录结构 2.基于SpringBoot的SpringMVC 4.整合Mybatis 5.整合Druid连接池 6.整合Junit4 7.整合Logback 8.整合PageHelper 9.SpringBoot整合Thymeleaf ​编辑 【附录】springboot的pom.xml 1.介绍 Spring框架的优点是方便解耦、简化开…

Python -- GUI图形界面编程—GUI编程实例 博主也在持续学习中[ 持续更新中!!! 欢迎白嫖 也求粉啊啊啊~ ]

本文介绍了GUI的图形界面编程&#xff08;相关视频是哔站上的应该搜这个题目就能找到&#xff09;&#xff0c;文章还是很基础的&#xff0c;反正我是小白从0开始&#xff0c;主要的结构tinkter库、重要组件简介&#xff08;这个不用死记硬背 用的时候再说&#xff09;、Label&…