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

news2025/1/10 20:32:36

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,说明左右子树不是平衡二叉树,或者根结点的左右子树高度相差超过1
        if(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;//记录当前结点为prev

        Convertchild(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;//如果是#就直接返回null
        if(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.coloradmin.cn/o/2050728.html

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

相关文章

C++适配windows和linux下网络编程TCP简单案例

C网络编程 网络协议是计算机网络中通信双方必须遵循的一套规则和约定&#xff0c;用于实现数据的传输、处理和控制。这些规则包括了数据格式、数据交换顺序、数据处理方式、错误检测和纠正等。网络协议是使不同类型的计算机和网络设备能够相互通信的基础&#xff0c;是网络通信…

PDF转markdown工具:magic-pdf

1. magic-pdf 环境安装 conda create -n MinerU python3.10 conda activate MinerU pip install boto3>1.28.43 -i https://pypi.tuna.tsinghua.edu.cn/simple/ pip install magic-pdf[full]0.7.0b1 --extra-index-url https://wheels.myhloli.com -i https://pypi.tuna.t…

SSA-SVM多变量回归预测|樽海鞘群优化算法-支持向量机|Matalb

目录 一、程序及算法内容介绍&#xff1a; 基本内容&#xff1a; 亮点与优势&#xff1a; 二、实际运行效果&#xff1a; 三、算法介绍&#xff1a; 四、完整程序下载&#xff1a; 一、程序及算法内容介绍&#xff1a; 基本内容&#xff1a; 本代码基于Matlab平台编译&a…

Chrome浏览器更改默认User-Agent

一、业务需求 二、插件下载 三、插件使用 原创文章&#xff0c;请勿转载&#xff01; 详细教程教你如何更改默认浏览器的User-Agent&#xff0c;几分钟足以&#xff01; 一、业务需求 当我们遇到一些特定的UA才能访问的网址时&#xff0c;我们就可以通过一些手段来修改我们浏…

Python之字符串练习题(下)

21.nameStr“Albert Einstein"&#xff0c;如何使用字符串运算符“:”来提取 nameStr 中的名和姓? mingnameStr[:6] xingnameStr[7:]23.下面哪些语句在运行时不会出错? (a)var xyz ’ * 10.5 (b)var ‘xyz’ * ‘5 ©var‘’xyz’*5 (d)var‘xyz’*5.0 重复运算符…

HTML静态网页成品作业(HTML+CSS)——美食企业介绍设计制作(1个页面)

&#x1f389;不定期分享源码&#xff0c;关注不丢失哦 文章目录 一、作品介绍二、作品演示三、代码目录四、网站代码HTML部分代码 五、源码获取 一、作品介绍 &#x1f3f7;️本套采用HTMLCSS&#xff0c;未使用Javacsript代码&#xff0c;共有1个页面。 二、作品演示 三、代…

在亚马逊云科技上对Stable Diffusion模型提示词、输出图像内容进行安全审核

项目简介&#xff1a; 小李哥将继续每天介绍一个基于亚马逊云科技AWS云计算平台的全球前沿AI技术解决方案&#xff0c;帮助大家快速了解国际上最热门的云计算平台亚马逊云科技AWS AI最佳实践&#xff0c;并应用到自己的日常工作里。 本次介绍的是如何在亚马逊云科技机器学习托…

HighPoint SSD7749M2:128TB NVMe 存储卡实现28 GB/s高速传输

HighPoint Technologies推出了一款全新的SSD7749M2 RAID卡&#xff0c;能够在标准的桌面工作站中安装多达16个M.2 SSD&#xff0c;实现高达128TB的闪存存储。该卡通过PCIe Gen4 x16接口提供高达28 GB/s的顺序读写性能。这些令人瞩目的性能规格伴随着高昂的价格标签。 #### 技术…

ArcGIS Pro基础:设置快速访问工具栏

上图【红色框线】内显示就是快速访问工具栏&#xff0c;访问非常方便&#xff0c;不需要切换到选项卡了 上图显示&#xff0c;可以勾选或者取消进行设置&#xff0c;通过【更多命令】可以选择更多的工具 如上图所示&#xff0c;可以选择自己经常使用的命令&#xff0c;可以输入…

手撕线程池

1.手撕线程池原理图 2.代码实现 // 手撕线程池 public class Main {public static void main(String[] args) {ThreadPool threadPool new ThreadPool(1,1000,TimeUnit.MILLISECONDS,1,(queue, task) -> {queue.putByTime(task,1500,TimeUnit.MILLISECONDS);});for (int i…

LangChain 实战演练:借助 LangChain SQL Agent 与 GPT 实现文档智能分析及交互

LangChain实战&#xff1a;利用LangChain SQL Agent和GPT进行文档分析和交互 我最近接触到一个非常有趣的挑战&#xff0c;涉及到人工智能数字化大量文件的能力&#xff0c;并使用户可以在这些文件上提出复杂的与数据相关的问题&#xff0c;比如&#xff1a; 数据检索问题&…

【qt】基于tcp的消息发送

我们需要实现客户端发消息&#xff0c;服务端接收消息 服务端界面新增接收消息 实现客户端发送和清空 发送数据需要将发送栏的信息转化为QByteArray,然后使用socket的write发送过去 实现服务端的接收 效果演示 20240818_111603 代码展示 server Widget.h #ifndef WIDGET_H …

Java的File类与IO流

目录 1. java.io.File类的使用 1.1 概述 1.2 构造器 1.3 常用方法 1、获取文件和目录基本信息 2、列出目录的下一级 3、File类的重命名功能 4、判断功能的方法 5、创建、删除功能 1.4 练习 2. IO流原理及流的分类 2.1 Java IO原理 2.2 流的分类 2.3 流的API 3. …

如何在 Windows/Mac/在线/iPhone/Android 上将 PDF 转换为 Word

PDF&#xff08;便携式文档格式&#xff09;是一种流行的格式&#xff0c;广泛用于在数字电子设备中呈现文档。输出文件小且兼容性强&#xff0c;使 PDF 如此受欢迎。但是&#xff0c;编辑 PDF 文件并非免费。您无需购买 PDF 编辑器&#xff0c;而是可以将 PDF 转换为 Word 进行…

「OC」NSPredicate —— 使用谓词过滤元素

「OC」NSPredicate —— 使用谓词过滤元素 文章目录 「OC」NSPredicate —— 使用谓词过滤元素前言介绍常见用法**比较运算符****逻辑运算符****字符串比较运算符****聚合运算符****用于字典或者类当中****格式说明符&#xff08;占位符&#xff09;** 实际运用总结参考文章 前…

05创建型设计模式——原型模式

一、原型模式简介 原型模式&#xff08;Prototype Pattern&#xff09;模式是一种对象创建型模式&#xff0c;它采取复制原型对象的方法来创建对象的实例。使用原型模式创建的实例&#xff0c;具有与原型一样的数据。 1&#xff09;由原型对象自身创建目标对象。换句话说&…

python基础语法 010 类和对象-3 方法

1.3 方法 属性表示是一个类当中的成员或类的特征&#xff0c;而方法是&#xff1f;&#xff1f; 方法&#xff1a;表示类、对象的行为&#xff0c;方法本质上是函数&#xff0c;是一个特殊的函数 属性名称一般为名词&#xff0c;方法名称一般为动词 1.3.1 方法 VS 属性 1、…

24/8/17算法笔记 DDPG算法

深度确定性策略梯度&#xff08;DDPG&#xff09;算法是一种用于解决连续动作空间强化学习问题的算法。它结合了确定性策略梯度&#xff08;DPG&#xff09;和深度学习技术的优点&#xff0c;通过Actor-Critic框架进行策略和价值函数的近似表示。DDPG算法的关键组成部分包括经验…

【RAG综述】北京大学检索增强技术综述

RAG for AIGC ​ 图 1 描述了一个典型的 RAG 过程。给定一个输入查询&#xff0c;检索器识别相关的数据源&#xff0c;检索到的信息与生成器交互以改进生成过程。根据检索结果如何增强生成&#xff0c;有几种基础范式&#xff08;简称基础&#xff09;&#xff1a;它们可以作为…

STM32的蜂鸣器

蜂鸣器分为有源蜂鸣器和无源蜂鸣器。 有源蜂鸣器&#xff1a;内部有震荡源&#xff0c;只要通电即可自动发出固定频率的声音。&#xff08;频率固定无 法控制音色&#xff09; 。 无源蜂鸣器&#xff1a;内部无震荡源&#xff0c;需要外部脉冲信号驱动发声&#xff0c;声音频…