初阶数据结构——二叉树题目

news2024/9/23 15:21:57

文章目录

  • 一、单值二叉树
  • 二、检查两颗树是否相同
  • 三、另一棵树的子树
  • 四、二叉树的前序遍历
  • 五、对称二叉树


一、单值二叉树

单值二叉树

如果二叉树每个节点都具有相同的值,那么该二叉树就是单值二叉树。只有给定的树是单值二叉树时,才返回 true;否则返回 false。

在这里插入图片描述
需要保证全部都相等,自然就需要左右子树都没问题。先想一个小问题,当遍历一个子树时,最终会遇到空,遇到空就要返回true,让它安全返回,不影响判断,这里也就说我们需要递归来遍历。那么现在从根开始,首先有一个判断,如果是空就返回true,跳过这个判断后,如果进行下一步?我们要让根和其他所有数字都相等,这其中最容易判断的就是根的左右子树是否相等,所以可能会写出这一个判断语句

if(root->val != root->right->val)

这个语句还欠缺考虑。要知道,现在我们的思路是用一个根节点去和它的两个子树比较是否相等,前提是两个子树都存在。前面的判断空是在判断root,也就是判断这个根节点,并没有判断它的子树们,所以应该这样写:if(root->right && root->right->val) 。如果符合条件了,那么这就不是单值二叉树,就得返回false了,返回的false也必须让之前的递归全部都false,最终才是false。

先不想这个,回到刚才的代码,我们只写了右边,还需要写左边,也是一样,也就是两个if,都需要判断。写完这三个判断后,就得递归了。前面说到false得让整体,所有的递归都为false,并且从题目中也知道,左右子树节点的值都得等于根才行,所以当往下继续遍历的时候,需要用&&来连接

return isUnivalTree(root->left) && isUnivalTree(root->right);

整体的代码

bool isUnivalTree(struct TreeNode* root) 
{
    if(!root) return true;
    if(root->left && root->val != root->left->val)
        return false;
    if(root->right && root->val != root->right->val)
        return false;
    return isUnivalTree(root->left) && isUnivalTree(root->right);
}

这道题也就结束了。题解中还有一种写法,是在判断左和右是否相等时进入递归,但这样不妥,如果从根开始,它的右子树节点的值就不相等,而程序在前面判断左子树时,如果相等,就开始了继续找左子树的递归,那么就白白浪费空间和时间了,所以现在现有的左右子树判断完再递归更好。

二、检查两颗树是否相同

相同的树

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

在这里插入图片描述
在这里插入图片描述
两棵树比较,值要相等,结构要相同。从根开始,如果两个值相等,这肯定符合要求,但是这时候不能返回true,我们还要继续往下判断,让递归进行下去,去看子树的情况,判断结构是否相同,但是不相等肯定就不行,就不是相同的树,所以可以写如果值不相等,就返回false。要让程序能够持续到最低层,来判断整体的结构是否相同,就得让其他判断条件也不能阻碍递归的前进,直到我们来到空,比如上面的例一中,2的左子树,这时候为空,如果另一棵树此时也是空,那就没问题,返回true,再往回走,去判断它的父节点的右子树;如果一个为空,一个不为空,那肯定不行,就直接返回false。而这里有一个巧妙的写法,先写两个都是空的判断,如果不是,那就要么是一空一不空,要么两个都不空,那就可以写if(p == NULL || q == NULL) 有一个为空就说明结构不相同了,因为是一空一不空。

上面这段已经写了三个判断,这三个判断就足以完成题目的要求,在最后加一个左右子树的递归即可。

bool isSameTree(struct TreeNode* p, struct TreeNode* q){
    if(p == NULL && q == NULL) return true;
    if(p == NULL || q == NULL) return false;
    if (p->val != q->val) return false;
    return isSameTree(p->left, q->left) && isSameTree(p->right, q->right);
}

三、另一棵树的子树

另一棵树的子树

给你两棵二叉树 root 和 subRoot 。检验 root 中是否包含和 subRoot 具有相同结构和节点值的子树。如果存在,返回 true ;否则,返回 false 。二叉树 tree 的一棵子树包括 tree 的某个节点和这个节点的所有后代节点。tree 也可以看做它自身的一棵子树。
在这里插入图片描述
在这里插入图片描述

既然要找子树,也就是要找到root中subRoot相同的一部分,这里就能用到刚才写的isSameTree。root有很多个子树,我们只能一个个比较,看看是否和subRoot相同,从根开始,整棵树也是root的子树,所以从root开始比较,如果root和subRoot是相同的树,那么就返回true。如果一次比较,发现不相同,程序得继续往下寻找,像例2那样,2下面还有一个0,那么从4开始比较,下面的部分就不相同,不相同,什么也不返回,继续找4的左子树和右子树进行比较。这里会想到我们要写两个式子,一个参数中有root->left,另一个是root->right,这两个只要有一个是true就说明是子树,那么程序就可以结束了,所有用或。一直往下比较,什么时候停止?如果一条路线到了空,说明这一路上的节点下的树都不和subRoot相同,那就说明这条路都不符合条件,那就返回false,返回false也不要紧,因为之前已经写了或,所以程序还会判断另一条路线是否可行,才会给出最终结果。

bool isSameTree(struct TreeNode* p, struct TreeNode* q) {
    if(p == NULL && q == NULL) return true;
    if(p == NULL || q == NULL) return false;
    if(p->val != q->val) return false;
    return isSameTree(p->left, q->left) && isSameTree(p->right, q->right);
}

bool isSubtree(struct TreeNode* root, struct TreeNode* subRoot) {
    if(!root) return false;
    if(isSameTree(root, subRoot)) return true;
    return isSubtree(root->left, subRoot) || isSubtree(root->right, subRoot);
}

四、二叉树的前序遍历

前序遍历

给你二叉树的根节点 root ,返回它节点值的 前序 遍历。

在这里插入图片描述
在这里插入图片描述

用递归算法解。前序遍历是比较简单的,不过这里要求把遍历的结果放到一个数组中,*returnSize是数组大小,最后返回数组。虽然提示中给了节点数目范围,但用一个函数来计算给的二叉树的节点数目更适合所有树。

int TreeSize(struct TreeNode* root)
{
    if root == NULL ? 0 : TreeSize(root->left) + TreeSize(root->right) + 1;
}

void preorder(struct TreeNode* root, int* array, int* i)
{
    if(root == NULL)
    {
        return;
    }
    array[(*i)++] = root->val;
    preorder(root->left, array, i);
    preorder(root->right, array, i);
}

int* preorderTraversal(struct TreeNode* root, int* returnSize){
    *returnSize = TreeSize(root);
    int* array = (int*)malloc(sizeof(int) * (*returnSize));
    int i  = 0;
    preorder(root, array, &i);
    return array;
}

五、对称二叉树

对称二叉树

给你一个二叉树的根节点 root,检查它是否轴对称。

在这里插入图片描述
在这里插入图片描述

对称二叉树,根的左右子树需要比较,看是否对称,这里能够想到判断相同,不过有一定差别,根节点值同样也要相等,左子树和另一个的右子树比较,右子树和另一个的左子树比较。

另一个思路就是翻转二叉树,把左右子树翻转过来,那么就可以直接比较相同了,翻转不难,大事化小,遍历最低一层的子树,然后逐个翻转,往上走,最后完成翻转。但其实这个思路不行,如果翻转二叉树,那么翻转后原二叉树就不存在了,我们只能复制一份,然后再翻转才行,但是复制又得走一遍递归了,所以这个思路更复杂。

bool isSameTree(struct TreeNode* p, struct TreeNode* q){
    if(!p && !q)
    {
        return true;
    }
    if((p == NULL || q == NULL) || (p->val != q->val))
    {
        return false;
    }
    return isSameTree(p->left, q->right) && isSameTree(p->right, q->left);
}

bool isSymmetric(struct TreeNode* root){
    if(root == NULL)
    {
        return true;
    }
    return isSameTree(root->left, root->right);
}

这里把两个return false的语句合并到了一起。

结束。

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

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

相关文章

AD原理图检查ERC(编译检查)

原理图的编译: 原理图界面选择菜单栏的:工程---->Compile PCB Project 也可以项目管理栏右击对应项目文件 在右下角,点击panels---->Message,就可以打开Message界面 原理图的常用检测: 原理图界面选择菜单…

kv键值对快速转换为json串(字典类型) | 批量添加双引号

从浏览器中复制的以下数据, 并不能直接使用 refresh:0 start:0 count:20 selected_categories:%7B%7D uncollect:false playable:true tags:在python中需转为字典类型 {refresh: 0,start: 0,count: 20,selected_categories: %7B%7D,uncollect: false,playable: true,tags: , …

SIMD系列-GATHER/SCATTER操作

SIMD系列-GATHER/SCATTER操作 众所周知,SIMD寄存器可以使用LOAD/STORE操作与标量域(或者更准确的说是内存)进行通信。这些操作的缺点是:只允许移动内存中连续的数据元素。然而,我们代码中,经常需要访问非连…

浅谈大数据软件的功能性分析

在当今时代的潮流中,工作中遇到大数据处理的时候非常多,因此需要一些大数据分析软件帮助人们进行工作。由于这些软件针对的对象不同,因此使用方法也不同,那么为了帮助更多的人了解大数据分析软件,我们就对这些软件的功…

【Linux命令200例】mc一个十分实用的文件管理器

🏆作者简介,黑夜开发者,全栈领域新星创作者✌,2023年6月csdn上海赛道top4。 🏆本文已收录于专栏:Linux命令大全。 🏆本专栏我们会通过具体的系统的命令讲解加上鲜活的实操案例对各个命令进行深入…

ARM裸机-4

1、什么是交叉编译 1.1、两种开发模式 非嵌入式开发,A(类)机编写(源代码)、编译得到可执行程序,发布给A(类)机运行。 嵌入式开发,A(类)机编写&am…

【PWN · Stack Smash】[2021 鹤城杯]easyecho

花式栈溢出——Canary保护是吧?接化发,拿来吧你 目录 前言 一、代码分析 0.保护 1.main函数 2.sub_CF0()函数 (v9指向的函数) 二、Stack Smash过程 0.原理简述 1.条件与准备 2.地址泄露 ①真实地址泄露 ②flag地址泄露…

解决问题:python PermissionError: [WinError 5]拒绝访问

重要:关闭PyCharm Community Edition 2022.3等与python相关的编程程序找到按照python解释器的位置python->右键>属性>安全->点击组或用户名"中的Users->编辑点击"组或用户名"中的Users->把"完全控制"打钩->应用->…

【Java】使用JDBC操作MySQL(快速入门+详解)

文章目录 1. JDBC概述2. JDBC快速入门2.1 下载驱动jar包2.2 数据准备2.3 创建工程2.4 编写代码 3. JDBC API详解3.1 DriverManager3.2 Connection3.2.1 获取执行SQL对象3.2.1 管理事务 3.3 Statement3.3.1 执行DML语句3.3.2 执行DDL语句 3.4 ResultSet3.4.1 ResultSet对象方法3…

ChatGPT 实现前一天

提出需求 个人输入需求: Java实现键盘输入日期 输出前一天,需要考虑润年和非润年,2月是否有29号,大月小月的区分等细节处理,不符合的有对应提示,不使用java包里的封装好的类 ChatGPT4分析出的语义&#xff…

人工智能安全-2-非平衡数据处理

0 提纲 现象与原因非平衡数据处理方法概览数据预处理层面特征层算法层面1 现象与原因 非平衡数据分类问题:在网络信息安全问题中,诸如恶意软件检测、SQL注入、不良信息检测等许多问题都可以归结为机器学习分类问题。这类机器学习应用问题中,普遍存在非平衡数据的现象。 产…

哈希函数如何工作 ?

动动发财的小手,点个赞吧! 作为一名程序员,您每天都会使用哈希函数。它们在数据库中用于优化查询,在数据结构中用于使速度更快,在安全性中用于保证数据安全。几乎每次与技术的交互都会以某种方式涉及哈希函数。 哈希函…

生命在于学习——APP渗透学习笔记

一、app渗透篇 1、Android 简介 自从 Android 被谷歌收购(2005 年),谷歌已经完成了整个开发,在过去的 9 年里,尤其是在安全方面,有很多变化。 现在,它是世界上最广泛使用的智能手机平台&#…

代码、低代码、无代码开发触手可及的低代码平台源码

基于moleculer微服务架构开发的低代码平台源码,代码、低代码、无代码开发触手可及。 一、低代码平台系统功能 【公司信息】 管理员可通过页面顶部设置菜单或者应用程序中设置应用进入到后台设置页面。 在公司信息页面可进行基础信息修改,启用用户自助…

我在CSDN创作的第五十天

这篇文章主要是写给自己的,是对自己现在阶段的一个认识,6月10号,我在CSDN发布了第一篇文章,距离现在不多不少,刚刚好是50天,期间创作的都是C语言的一些内容,我创作的文章也都是我现在所学的知识…

Django系列之DRF简单使用

基于ModelViewSets的简单使用 models.py from django.db import modelsclass AuthorDetail(models.Model):gender models.CharField(max_length8)birthday models.DateField()telephone models.BigIntegerField()addr models.CharField(max_length64)class Author(models…

手机的python怎么运行文件,python在手机上怎么运行

大家好,小编来为大家解答以下问题,手机上的python怎么运行程序,手机的python怎么运行文件,今天让我们一起来看看吧! 1、python程序怎么在手机上运行 python语言应用很广泛,自己也很喜欢使用它,其…

自学网络安全(黑客)入门

自学网络安全入门可以按照以下步骤进行: 确定学习目标:网络安全是一个广泛的领域,包括密码学、网络防御、漏洞利用等方面。确定自己想要学习的具体方向,可以更好地规划学习路线。 学习基础知识:网络安全的基础知识包括…

Leetcode周赛 | 2023-7-30--我真是个废物

2023-7-30--我真是个废物 题1体会我的代码 题2体会我的代码 题3体会我的代码 题1 体会 根本没想到用双指针。原因是,没想到还要用一个字典去维护子数组中各个数字的出现频次,以及出现频次不小于1 (也就是大于0) 的数字个数。 这里的双重循环也很巧妙&am…

牛客 排座椅(贪心)

上课的时候总有一些同学和前后左右的人交头接耳,这是令小学班主任十分头疼的一件事情。不过,班主任小雪发现了一些有趣的现象,当同学们的座次确定下来之后,只有有限的D对同学上课时会交头接耳。 同学们在教室中坐成了 M 行 N 列&…