Java-数据结构-二叉树习题(1)

对于二叉树的学习,主要的还是得多多练习~毕竟二叉树属于新的知识,并且也并不是线性结构,再加上经常使用递归的方法解决二叉树的问题所以代码的具体流程还是无法看到的,只能通过画图+想象,所以还是必须多加练习,使自己见识的题型更多,才会熟能生巧~

第一题、相同的树

📚 思路提示

这一题还是很好想的~,对于比较两个相同的树,我们只需要像之前模拟实现二叉树的方法一样,将它拆解成 " 左子树和右子树的子问题 " 将两个树的左子树与左子树进行比较,右子树与右子树进行比较。

并且再通过递归的方式不断对子树再次执行 " 拆解成新的左子树和右子树 比较对应子树是否相同 "的操作。

直到从最底层的子树(叶子结点)递归回到两个数的根节点时,如果中途出现过 false 那么返回的就是 false ,反之则返回 true。

而其中结点的比较过程,需要判断的问题有这几种

📕 如果 p == null 并且 q == null 则代表同时达到叶子节点,返回 true 

📕 如果 p 和 q 没有进入上述判断语句,并且此时 p == null 或者 q == null 则代表有一方提前访问到了子树,则代表两棵子树的长度不相同,返回 false

📕 如果 p 和 q 都没进入上述两个判断语句,那么此时 p 和 q 都不为 null ,此时正常对它们的值进行比较,如果 p.val 不等于 q.val 则返回false

📕 最后递归函数,两次函数传参 " (p.left,q.left) && (p.right,q.right) ",只有全 true 的时候,才能最后返回 true 

图示

📖 代码示例

class Solution {
    public boolean isSameTree(TreeNode p, TreeNode q) {
        if(p == null && q == null){
            return true;
        }
        if(p == null || q == null || p.val != q.val){
            return false;
        }
        return isSameTree(p.left,q.left) && isSameTree(p.right,q.right); 
    } 
}

第二题、另一棵树的子树

📚 思路提示

对于此题,其实就是上一题的引申~我们想要判断,一棵树是否是另一棵树的子树,那么我们首先要在另一棵树中找到这棵树的根节点

找到根节点后,我们就可以对这棵树进行判断啦~没错的,也就是判断它是否为相同的树,那么我们直接使用上一题的方法即可,首先找到根节点,然后再调用"判断是否为相同树"的方法进行递归即可

那么如何找到这个根结点呢?有以下的步骤

📕 不断递归该方法,分别传参判断(root.left)和(root.right),与subRoot的根节点是否相同(直接通过判断两棵树是否相等的方法即可)

📕 如果 root 等于 null 则返回 false 代表该子树中没找到那棵相同子树,退出递归

📕 如果"两树相同方法返回了true",则返回 true,代表该子树中找到了那棵相同子树,退出递归 

图示

📖 代码示例

class Solution {
    public boolean isSubtree(TreeNode root, TreeNode subRoot) {
        if(root == null){
            return false;
        }
        if(isSameTree(root,subRoot)){
            return true;
        }
        return isSubtree(root.left,subRoot) || isSubtree(root.right,subRoot);
    }
        public boolean isSameTree(TreeNode p, TreeNode q) {
        if(p == null && q == null){
            return true;
        }
        if(p == null || q == null || p.val != q.val){
            return false;
        }
        return isSameTree(p.left,q.left) && isSameTree(p.right,q.right); 
    } 
}

第三题、翻转二叉树

想要翻转二叉树,就需要我们对树进行遍历,所以该题有多种解法,取决于它采用何种遍历。

(需要注意的是,不是将根节点下的左右子树翻转就好了,而是需要每棵树的子树都要进行翻转)

📚 思路提示[前/中/后序遍历]

还是很简单的思路,只需要不断的递归函数,再将其中的结点互换即可~这里就不再过多赘述啦~我们直接看图片

图示[前/中/后序遍历](1)

📖 代码示例(1)

    public TreeNode invertTree(TreeNode root){
        if(root == null){
            return null;
        }
        TreeNode tmp = root.left;
        root.left = root.right;
        root.right = tmp;
        invertTree(root.left);
        invertTree(root.right);
        return root;
    }

上述方法是通过借助中间变量 tmp 来实现的,接下来我们不用 tmp,而是将左右子树两个结点存储,再递归回去分别进行交换。

图示[前/中/后序遍历](2)

📖 代码示例(2)

class Solution {
    public TreeNode invertTree(TreeNode root) {
        if(root == null){
            return null;
        }
        TreeNode left = invertTree(root.left);
        TreeNode right = invertTree(root.right);
        root.left = right;
        root.right = left;
        return root;
    }
}

📚 思路提示[层序遍历]

层序遍历,在上一篇博客中我们已经讲解到了~就是将每一层的结点按照从左至右,从上至下的顺序存储到队列中,并且通过循环,将队列中的元素(一层的结点)依次出队列打印出来。

而在这题中,我们只需要在结点出队列的时候,同时将每个结点的左右子结点进行互换即可~思路还是很简单的,我们直接看图看代码~~

图示[层序遍历]

📖 代码示例(3)

class Solution {
    public TreeNode invertTree(TreeNode root) {
        if (root == null) {
            return null;
        }
        Deque<TreeNode> deque = new LinkedList<>();
        deque.push(root);
        while (!deque.isEmpty()) {
            TreeNode node = deque.removeLast();
            if (node.left != null) {
                deque.push(node.left);
            }
            if (node.right != null) {
                deque.push(node.right);
            }
            TreeNode tmp = node.left;
            node.left = node.right;
            node.right = tmp;
        }
        return root;
    }
}

第四题、反转二叉树的奇数层

我们之所以先讲了一个翻转二叉树,其实目的就是引出这道题~至于这道题应该怎么求解,其实也是换汤不换药,在这里我们提供两种解法:

📕 层序排列

📚 思路提示(1)

经过上面的那道题,相信大家对层序遍历也有了比较深刻的理解了~而对于这道题也并不难,上面的代码要求我们将所有层的左右结点都进行翻转,这题则是将奇数层的左右结点进行翻转。

所以我们只需要在循环外部定义一个变量,通过这个变量来记录每次遍历时队列中计入结点对应为第几层,再将奇数层的结点相互调换即可~

使用该方法解题有以下几点需要注意

📕 注意题中的根节点层数是以0开始的,而并非是1

📕 外层while循环不能再像上一题一样,每出队一个结点(及子树),就判断一次while循环,这样就无法获取层数

📕 而想修改上述问题,我们就需要在while循环内部再设置一个循环我们定义此时的队列元素个数为len,定义条件while(len-- > 0),并且将入队列和出队列的操作都在这个循环内部进行,这样就能解决查找层数不准确的问题了。

📕 同时,如果我们想做到上述,在一次while大循环中解决多次结点入队列出队列,那么对应的,我们也要同时应对交换结点这一步,我这里采用的方法是"当层数为奇数时,将队列中结点存入一个顺序表中,通过双指针的方法,将其中结点值进行翻转"~注意,这里不推荐使用链表,因为速度的消耗极大:

顺序表:

链表:

图示(1)

📖 代码示例(1)

class Solution {
    public TreeNode reverseOddLevels(TreeNode root) {
        if (root == null) {
            return null;
        }
        int num = 0;
        Deque<TreeNode> deque = new LinkedList<>();
        deque.push(root);
        while (!deque.isEmpty()) {
            int len = deque.size();
            if (num % 2 != 0) {
                List<TreeNode> list = new ArrayList<>(deque);
                for (int i = 0, j = list.size() - 1; i < j; i++, j--) {
                    TreeNode tmpl = list.get(i);
                    TreeNode tmpr = list.get(j);
                    int tmp = tmpl.val;
                    tmpl.val = tmpr.val;
                    tmpr.val = tmp;
                }
            }
            while(len-- > 0){
                TreeNode node = deque.removeLast();
                if (node.left != null) {
                    deque.push(node.left);
                }
                if (node.right != null) {
                    deque.push(node.right);
                }
            }
            num++;
        }
        return root;
    }
}

📕 分解子树法

📚 思路提示(2)

这种解法相对于上一种解法就要简单许多了,同时效率也达到了显著的提升~既不用队列,也不用顺序表,更用不上循环交换节点的值!~

果然树还是得用递归呀~

其实还是很好理解的,平时我们进行结点的交换,只是传入root的左结点和右结点,就能够通过递归将所有结点都互换

那么我们只需要创建一个方法,使它的参数再多一个int类型,每次递归都在它的原基础上+1,那么就可以很清晰的分辨出是奇数层还是偶数层

至于过程也就是和平时的翻转结点多了个判断层数的步骤,这里就不再过多的画图赘述啦~我们直接看代码,包看得懂的。

📖 代码示例(2)

class Solution {
    public TreeNode reverseOddLevels(TreeNode root) {
        if (root == null) {
            return null;
        }
        move(root.left, root.right, 1);
        return root;
    }
    public void move(TreeNode left, TreeNode right, int num) {
        if(left == null || right == null){
            return;
        }
        if (num % 2 != 0) {
            int tmp = left.val;
            left.val = right.val;
            right.val = tmp;
        }
        move(left.left, right.right, num + 1);
        move(left.right, right.left, num + 1);
    }
}

那么这次关于二叉树的习题相关知识,就为大家分享到这里啦,作者能力有限,如果有讲得不清晰或者不正确的地方,还请大家在评论区多多指出,我也会虚心学习的!那我们下次再见哦

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

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

相关文章

彩色图像面积计算一般方法及MATLAB实现

一、引言 在数字图像处理中&#xff0c;经常需要获取感兴趣区域的面积属性&#xff0c;下面给出图像处理的一般步骤。 1.读入的彩色图像 2.将彩色图像转化为灰度图像 3.灰度图像转化为二值图像 4.区域标记 5.对每个区域的面积进行计算和显示 二、程序代码 %面积计算 cle…

计算机网络 (41)文件传送协议

前言 一、文件传送协议&#xff08;FTP&#xff09; 概述&#xff1a; FTP&#xff08;File Transfer Protocol&#xff09;是互联网上使用得最广泛的文件传送协议。FTP提供交互式的访问&#xff0c;允许客户指明文件的类型与格式&#xff08;如指明是否使用ASCII码&#xff0…

vscode的安装与使用

下载 地址&#xff1a;https://code.visualstudio.com/ 安装 修改安装路径&#xff08;不要有中文&#xff09; 点击下一步&#xff0c;创建桌面快捷方式&#xff0c;等待安装 安装中文插件 可以根据自己的需要安装python和Jupyter插件

用Cursor生成一个企业官网前端页面(生成腾讯、阿里官网静态页面)

用Cursor生成一个企业官网前端页面 第一版&#xff1a; <!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><…

简要认识Web技术三剑客:HTMLCSSJavaScript

目录 一、web标准二、什么是HTML三、什么是CSS四、什么是JavaScript 黑马JAVAWeb飞书在线讲义地址&#xff1a; https://heuqqdmbyk.feishu.cn/wiki/LYVswfK4eigRIhkW0pvcqgH9nWd 一、web标准 Web标准也称网页标准&#xff0c;由一系列的标准组成&#xff0c;大部分由W3C&…

python(25) : 含有大模型生成的公式的文本渲染成图片并生成word文档(支持flask接口调用)

公式样例 渲染前 \[ \sqrt{1904.615384} \approx 43.64 \] 渲染后 安装依赖 pip install matplotlib -i https://mirrors.aliyun.com/pypi/simple/ requestspip install sympy -i https://mirrors.aliyun.com/pypi/simple/ requestspip install python-docx -i https…

2024CVPR《HomoFormer》

这篇论文提出了一种名为HomoFormer的新型Transformer模型,用于图像阴影去除。论文的主要贡献和创新点如下: 1. 研究背景与动机 阴影去除的挑战:阴影在自然场景图像中普遍存在,影响图像质量并限制后续计算机视觉任务的性能。阴影的空间分布不均匀且模式多样,导致传统的卷积…

PE文件:节表-添加节

在所有节的空白区域都不够存放我们想要添加的数据时&#xff0c;这个时候可以通过添加节来扩展我们可操作的空间去存储新的数据&#xff08;如导入表、代码或资源&#xff09;。 过程步骤 1.判断是否有足够的空间添加节表 PE文件的节表紧跟在PE头之后&#xff0c;每个节表的…

窥探QCC518x/308x系列与手机之间的蓝牙HCI记录与分析 - 手机篇

今天要介绍给大家的是, 当我们在开发高通耳机时如果遇到与手机之间相容性问题, 通常会用Frontline或Ellisys的Bluetooth Analyzer来截取资料分析, 如果手边没有这样的仪器, 要如何窥探Bluetooth的HCI log.这次介绍的是手机篇. 这次跟QCC518x/QCC308x测试的手机是Samsung S23 U…

【MySQL】数据库约束和多表查询

目录 1.前言 2.数据库约束 2.1约束类型 2.2?NULL约束 2.3 NUIQUE&#xff1a;唯一约束 2.4?DEFAULT&#xff1a;默认值约束 2.5?PRIMARY KEY&#xff1a;主键约束 2.6 FOREIGN KEY&#xff1a;外键约束 1.7?CHECK约束 3.表的设计? 3.1一对一 3.2一对多 3.3多…

Unity HybridCLR Settings热更设置

需要热更的程序集放到 热更新Assembly Definitions中。 记得补充元数据AOT dlls 打包完成后遇到TypeLoadException: could not load type 时 可能需要在Assets/link.xml中增加对应的设置 <assembly fullname"your assembly" preserve"all"/> link…

LLM - 大模型 ScallingLaws 的迁移学习与混合训练(PLM) 教程(3)

欢迎关注我的CSDN&#xff1a;https://spike.blog.csdn.net/ 本文地址&#xff1a;https://spike.blog.csdn.net/article/details/145212097 免责声明&#xff1a;本文来源于个人知识与公开资料&#xff0c;仅用于学术交流&#xff0c;欢迎讨论&#xff0c;不支持转载。 Scalin…

【Python】Selenium根据网页页面长度,模拟向下滚动鼠标,直到网页底部的操作

最近在弄selenium的爬取的过程中&#xff0c;我发现一些网站上的表格&#xff0c;是需要手动拉到底部才能加载完成的。 如果没有拉到底部&#xff0c;那么在获取网页表格的时候&#xff0c;表格就会只有显示的一部分&#xff0c;页面就不完整。 所以我就整理了一些模拟滚动鼠…

vue2制作长方形容器,正方形网格散点图,并且等比缩放拖动

需求&#xff1a;有个长方形的容器&#xff0c;但是需要正方形的网格线&#xff0c;网格线是等比缩放的并且可以无线拖动的&#xff0c;并且添加自适应缩放和动态切换&#xff0c;工具是plotly.js,已完成功能如下 1.正方形网格 2.散点分组 3.自定义悬浮框的数据 4.根据窗口大小…

Lora理解QLoRA

Parameter-Efficient Fine-Tuning (PEFT) &#xff1a;节约开销的做法&#xff0c;fine-tune少量参数&#xff0c;而不是整个模型&#xff1b; Low-Rank Adaptation (LoRA) &#xff1a;是PEFT的一种&#xff1b;冻结原参数矩阵&#xff0c;只更新2个小参数矩阵。 原文经过对比…

Elasticsearch:Jira 连接器教程第二部分 - 6 个优化技巧

作者&#xff1a;来自 Elastic Gustavo Llermaly 将 Jira 连接到 Elasticsearch 后&#xff0c;我们现在将回顾最佳实践以升级此部署。 在本系列的第一部分中&#xff0c;我们配置了 Jira 连接器并将对象索引到 Elasticsearch 中。在第二部分中&#xff0c;我们将回顾一些最佳实…

联发科MTK6762/MT6762安卓核心板_4G智能模块应用

MT6762安卓核心板是一款工业级高性能、可运行 android9.0 操作系统的 4G智能模块。MT6762平台打造具备 AI 体验、先进双摄像头拍摄效果且具备丰富连接功能的智能手机主板。 MT6762安卓核心板 是一款髙性能低功耗的 4G 全网通安卓智能模块。此模块支持 2G/3G/4G 移动&#xff0c…

vue3+ts+uniapp 微信小程序(第一篇)—— 微信小程序定位授权,位置信息权限授权

文章目录 简介一、先看效果1.1 授权定位前&#xff0c;先弹出隐私协议弹框1.2 上述弹框点击同意&#xff0c;得到如下弹框1.3 点击三个点&#xff0c;然后点设置 1.4 在1.2步骤下&#xff0c;无论同意或者拒绝 二、manifest.json 文件配置三、微信公众平台配置3.1 登录进入微信…

网安快速入门之Windows命令

在Windows中 我们今天介绍几个命令&#xff1a; help copy dir cd type del ipconfig net netstat tasklist sc1. help 显示命令的帮助信息。或者显示Windows内置命令。 常用参数&#xff1a; <命令>&#xff1a;查看指定命令的帮助。 示例&#xff1a;help copy 显…

Red Hat8:搭建FTP服务器

目录 一、匿名FTP访问 1、新建挂载文件 2、挂载 3、关闭防火墙 4、搭建yum源 5、安装VSFTPD 6、 打开配置文件 7、设置配置文件如下几个参数 8、重启vsftpd服务 9、进入图形化界面配置网络 10、查看IP地址 11、安装ftp服务 12、遇到拒绝连接 13、测试 二、本地…