二叉树 —— OJ题目详解

news2024/11/15 7:57:34

1.二叉树的前序遍历

二叉树的前序遍历比较简单,但是在力扣上写这个接口需要注意几个点:

int* preorderTraversal(struct TreeNode* root, int* returnSize) {
    
}
  • preorderTraversal 的返回值是动态开辟的数组,里面存放的是前序遍历的顺序
  • int* returnSize 这个参数记录的是遍历到的数据个数,因为函数的返回值只能有一个,所以我们通它来记录,当用户需要数据个数时,直接查看该指针变量即可

 代码:


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

void _preOrder(struct TreeNode* root, int* a,int* i){
    if(root == NULL)
    return;

    a[*i] = root->val; //记录当前节点,到数组中
    (*i)++;            //数组下标+1

    _preOrder(root->left,a,i);  //接着遍历左子树
    _preOrder(root->right,a,i); //然后遍历右子树 

}

//returensize是记录数组的元素个数,我们要返回给用户的是遍历数的数组
int* preorderTraversal(struct TreeNode* root, int* returnSize) {

    *returnSize = TreeSize(root);//遍历树,得到数据个数

    int* a = (int*)malloc(sizeof(int) * (*returnSize));//动态开辟数组空间

    int i = 0;
    _preOrder(root ,a,&i);//前序遍历
    return a;

}

2.检查两棵树是否相同

思路: 

利用前序遍历,先比较当前节点是否相同,紧接着比较左子树与右子树

代码:

bool isSameTree(struct TreeNode* p, struct TreeNode* q) {
    if(p == NULL && q == NULL) //如果pq都为NULL,返回真
        return true;

    if(p == NULL || q == NULL)  //代码到这里,只有2种可能,1.pq其中一个为NULL,2两个都不为NULL
                               //如果其中一个为NULL,说明另一个一定不是NULL,则pq不相等,不用
        return false;          //比较了,返回false


    if(p->val != q->val)  // 代码到这,说明pq都不为NULL,直接比较即可

        return false;    //比较qp相等没有用意义,要看它们不相等,可以直接出结果

    return isSameTree(q->left,p->left) //在比较左右子树,右子树
    && isSameTree(q->right,p->right);
}

3.对称二叉树

 思路:

观察示例一:一颗对称的二叉树,我的左子树根节点 == 你的右子树根节点、我的右子树根节点 == 你的左子树根节点。有一个地方不符合此规则,则此树不是对称二叉树

所以示例一是一颗对称二叉树,我们代码则使用递归的方法,先比较当前两棵树的根节点是否相同,在比较这两颗树的左右子树是否对称

代码:

bool _isSymmetric(struct TreeNode* q,struct TreeNode* p)
{
    //先比较当前两颗子树的根节点是都相同
    if(p == NULL && q == NULL) 
        return true;

    if(p == NULL || q == NULL)  //代码到这里,只有2种可能,1.pq其中一个为NULL,2两个都不为NULL
        return false;

    if(p->val != q->val)// 比较根节点是否相同
        return false;

    return _isSymmetric(q->left,p->right)   //q节点的左子树,与p节点的右子树比
    && _isSymmetric(q->right,p->left);     //q节点的右子树,与p节点的左子树比
}
bool isSymmetric(struct TreeNode* root) {
    return _isSymmetric(root->left,root->right);
}

4.另一棵树的子树

思路:

题目给出了root树与subRoot树,让我们看看sybRoot树是否是root树中的一个子树

 1.那么我们首先要做的是:如何找出root树的所有子树?

其实这个很简单,我们只需要遍历到root树的每一个节点就相当于找到了root树的所有子树,因为每一个节点都是某棵树的根节点,通过根节点自然得到了一节树

2.找到了所有子树之后我们要做的自然依次与subRoot树比较,看有没有相同的树了

我们前面已经写过检查两颗树是否相同,直接移植过来就可以

代码:

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(q->left,p->left)
    && isSameTree(q->right,p->right);
}

bool isSubtree(struct TreeNode* root, struct TreeNode* subRoot){

    if(root == NULL)//subRoot树上的节点数量范围是[1, 1000],所以当遍历到的子树为NULL时返回false
        return false;

     //当某一个子树的根节点与subRoot根节点相同时,开始比较两棵树是否相同
     //当两颗树相同则直接出结果,不用接着去找了,返回ture 
    if(root->val == subRoot->val &&
    isSameTree(root,subRoot))
        return true;

    //接着去遍历左子树与右子树,一边找到了就不用再继续找了,整体就是前序遍历的去遍历每一颗子树
    return isSubtree(root->left,subRoot) || isSubtree(root->right,subRoot);
}

5.二叉树的构建及遍历

利用,用户输入的数组先构建一颗二叉树,在进行中序遍历即可 

代码:

#include <stdio.h>
#include<stdlib.h>
typedef char BTDataType;

typedef struct BinaryTreeNode {
    BTDataType _data;
    struct BinaryTreeNode* _left;
    struct BinaryTreeNode* _right;
} BTNode;

BTNode* BuyNode(BTDataType x) {

    BTNode* newnode = (BTNode*)malloc(sizeof(BTNode));
    if (newnode == NULL) {
        perror("Buynode()::malloc()");
        return newnode;
    }

    newnode->_data = x;
    newnode->_left = NULL;
    newnode->_right = NULL;
    return newnode;
}

// 二叉树中序遍历
void BinaryTreeInOrder(BTNode* root) {
    if (root == NULL) {
        return;
    }

    BinaryTreeInOrder(root->_left);//左子树
    printf("%c ", root->_data);//根节点
    BinaryTreeInOrder(root->_right);
}

// 通过前序遍历的数组"ABD##E#H##CF##G##"构建二叉树
BTNode* BinaryTreeCreate(BTDataType* a,int* pi) {

    //根,左子树,右子树

    if (a[(*pi)] == '#') {
        (*pi)++;
        return NULL;
    }

    BTNode* newnode = BuyNode(a[(*pi)++]);

    newnode->_left = BinaryTreeCreate(a,pi);
    newnode->_right  = BinaryTreeCreate(a,pi);

    return newnode;
}

int main() {
    char arr[101];
    scanf("%s",arr);
    int count = 0;
    BTNode* tree = BinaryTreeCreate(arr,&count);   //构建二叉树
    BinaryTreeInOrder(tree);                      //中序遍历二叉树
    return 0;
}

6.翻转二叉树

思路: 

依旧是使用递归,先翻转左子树,在翻转右子树。由于翻转后,左右子树的根节点没有动,最后在将根节点翻转即可完成当前树的翻转

代码:

void _invertTree(struct TreeNode* root)
{
    if(root == NULL)
    return;

    _invertTree(root->left);   //翻转左子树
    _invertTree(root->right);  //翻转右子树

    //在将自己左右子树的根节点交换,即可完成翻转
    struct TreeNode* temp = root->left;
    root->left = root->right;
    root->right = temp;
}
struct TreeNode* invertTree(struct TreeNode* root) {
    _invertTree(root);

    return root;
}

7.平衡二叉树

平衡二叉树: 每个节点的左右子树的深度相差不超过1

思路: 

遍历二叉树的每一个节点,算它们的高度差超过1吗,超过就不是平衡二叉树

代码:

int TreeHight(struct TreeNode* root)//求高度
{
    if(root == NULL)
    return 0;

    int left = TreeHight(root->left);
    int right = TreeHight(root->right);

    return left > right ? left + 1 : right + 1;
}

//走前序遍历,依次遍历每个节点,并求节点左子树与右子树的高度差 >1?
bool isBalanced(struct TreeNode* root) {
    if(root == NULL)
    return true;

    //比较当前节点左右子树高度差
    int left = TreeHight(root->left);   
    int right = TreeHight(root->right);
    if(abs(left-right) > 1)
    return false;

    if(isBalanced(root->left) == 0)  //遍历左子树
    return false;

    if(isBalanced(root->right) == 0)  //遍历右子树
    return false;

    return true; //代码到这说明它就是一颗平衡二叉树
}

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

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

相关文章

Python 获取今天(当天)、昨天(前一天)、前天(昨天的前一天)的开始时间、结束时间

描述&#xff1a;我这里是封装成DatetimeHelper工具类来调用 1.今天(当天)开始时间、结束时间 from datetime import datetime, timedeltaclass DatetimeHelper:# 获取今天(当天)的开始时间、结束时间(datetime类型)staticmethoddef getTodayStartEnd():# 获取当前的日期now …

JVM监控及诊断工具-命令行篇--jinfo命令介绍

JVM监控及诊断工具-命令行篇02-jinfo&#xff1a;实时查看和修改JVM配置参数 一 基本情况二 基本语法2.1查看jinfo -sysprops PIDjinfo -flags PIDjinfo -flag 具体参数 PID 2.2修改 三 拓展java -XX:PrintFlagsInitialjava -XX:PrintFlagsFinaljava -XX:PrintCommandLineFlags…

IP风险画像 金融行业的安全盾牌

在当今数字化时代&#xff0c;金融行业面临着前所未有的安全挑战。随着在线交易和数字银行业务的迅猛发展&#xff0c;欺诈和网络攻击的威胁也在不断增加。金融机构需要高效、可靠的安全解决方案来保护客户的资产和个人信息&#xff0c;防止各种形式的欺诈行为。 IP风险画像是…

el-date-picker手动输入日期,通过设置开始时间和阶段自动填写结束时间

需求&#xff1a;根据开始时间&#xff0c;通过填写阶段时长&#xff0c;自动填写结束时间&#xff0c;同时开始时间和节数时间可以手动输入 代码如下&#xff1a; <el-form ref"ruleForm2" :rules"rules2" :model"formData" inline label-po…

# Redis 入门到精通(四)-- linux 环境安装 redis

Redis 入门到精通&#xff08;四&#xff09;-- linux 环境安装 redis 一、linux 环境安装 redis – 基于 Linux 安装 redis 1、基于 Center 0S7 或者 unbunt-18.04 安装 Redis 1&#xff09;下载安装包wget http://download.redis.io/releases/redis-?.?.?.tar.gz 如&…

五、 计算机网络(考点篇)试题

A、B、C都没问题&#xff0c;选D。现在基本上所有的互联网网站都是https了&#xff0c;电子支付类的更不用说了。 简单邮件传输的协议是SMTP(发)和POP3(收)&#xff0c;分别是25和110。选B和B 网络分片技术&#xff0c;分割切片嘛。 选C&#xff0c;AES加密等级比较高了&#x…

关于SQLException: Illegal mix of collations (`utf8mb4_general_ci,IMPLICIT`)...错误

希望文章能给到你启发和灵感&#xff5e; 如果觉得文章对你有帮助的话&#xff0c;点赞 关注 收藏 支持一下博主吧&#xff5e; 阅读指南 开篇说明一、基础环境说明1.1 硬件环境1.2 软件环境 二、报错信息三、最后 开篇说明 记录一个查询错误 场景&#xff1a;数据库之间某表复…

Nginx的反向代理缓存

一 .Nginx的反向代理缓存 #代理缓存路径设置缓存保存的目录 #keys_zone设置共享内存占用的空间大小 #max_size缓存大小 #inactice 超过时间,则缓存自动清理 #use_temp_path 关闭临时目录proxy_cache_path /usr/local/nginx/upsteam_cache key_zone=mycache:5m max_size=…

51单片机STC89C52RC——19.1 SG90舵机(伺服电机)

目的/效果 独立按键K1&#xff0c;K2 实现加舵机减角度增减&#xff0c;LCD1602显示舵机转角度数&#xff08;上电默认90度&#xff09; 一&#xff0c;STC单片机模块 二&#xff0c;SG90舵机 2.1 简介 舵机只是我们通俗的叫法&#xff0c;它的本质是一个伺服电机&#xf…

活动预告|想更了解流式数据湖?亚马逊云科技数据开源软件-流式数据湖 Tech Talk来啦!

活动介绍 本次活动旨在探索在亚马逊云科技上构建和使用开源数据软件产品的一些最佳实践&#xff0c;特别关注流式数据湖的构建。活动将在线上举行&#xff0c;汇聚来自 AutoMQ Apache paimon和亚马逊云科技的顶尖专家&#xff0c;分享他们在这一领域的最新进展和实际经验。参与…

分类预测 | Matlab实现OOA-LSSVM鱼鹰算法优化最小二乘支持向量机多特征分类预测/故障诊断

分类预测 | Matlab实现OOA-LSSVM鱼鹰算法优化最小二乘支持向量机多特征分类预测/故障诊断 目录 分类预测 | Matlab实现OOA-LSSVM鱼鹰算法优化最小二乘支持向量机多特征分类预测/故障诊断分类效果基本介绍程序设计参考资料 分类效果 基本介绍 分类预测 | Matlab实现OOA-LSSVM鱼…

【Docker】Docker 的数据管理与镜像创建

目录 一.数据管理 1.数据卷 2.数据卷容器 二.端口映射 三.容器互联 四.Docker 镜像的创建 1.基于现有镜像创建 1.1.首先启动一个镜像&#xff0c;基于镜像创建容器&#xff0c;更新容器内容 1.2.将修改后的容器提交为新的镜像&#xff0c;需要使用该容器的 ID 号创建新…

git取消合并:--hard 或 --merge

第一步&#xff1a;查了git日志 git reflog如下&#xff0c;运行上述命令后&#xff0c;可以看见所有的提交哈希&#xff08;id&#xff09; 第二步 查看到上述所有的提交记录后&#xff0c;有如下方法去回退 方法1&#xff1a;--hard 确定上一次提交的哈希值 git reset…

低空经济持续发热,无人机培训考证就业市场及前景剖析

随着科技的不断进步和社会需求的日益增长&#xff0c;低空经济已成为全球及我国经济增长的新引擎。作为低空经济的重要组成部分&#xff0c;无人机技术因其广泛的应用领域和显著的经济效益&#xff0c;受到了社会各界的广泛关注。为满足市场对无人机人才的需求&#xff0c;无人…

object-C 解答算法:两数之和(leetCode-1)

两数之和(leetCode-1) 题目如下图:(也可以到leetCode上看完整题目,题号1) 解答方法一: 最简单的方法就是双指针遍历数组.代码如下 - (NSMutableArray *)sumOfTwoNumbers:(NSMutableArray *)array target:(int)target {NSMutableArray * resultArray [[NSMutableArray alloc…

怎样去除视频上的水印和文字,视频水印文本移除教程

在观看和分享视频时&#xff0c;我们经常会遇到带有水印或额外文字的情况。这些标记有时是为了版权保护&#xff0c;有时则是平台的标识&#xff0c;但在某些情况下&#xff0c;它们可能会干扰视频的观赏体验。本文将向你介绍常见的视频水印类型以及如何使用简鹿水印助手去除这…

漏洞复现 | Showdoc反序列化

非常简单的一个靶场 靶场地址&#xff1a;https://hack.zkaq.cn/ 打开靶场&#xff0c;弹出了这种登录框&#xff0c;这也成为了后面的一个坑点&#xff0c;记住这个登录框。 看到了注册功能&#xff0c;showdoc有注册功能我们就不用尝试前台SQL注入了&#xff0c;直接注册…

—张pdf怎么分割成多页,怎么把一个pdf分割

在数字化时代&#xff0c;pdf文件已经成为我们工作和生活中不可或缺的一部分。然而&#xff0c;有时候我们可能会遇到需要将一张pdf文件分割成多页的情况。无论是为了便于分享&#xff0c;还是为了满足特定的文档格式要求&#xff0c;这个任务都可能变得相当棘手。但别担心&…

python数据可视化(5)——绘制饼图

课程学习来源&#xff1a;b站up&#xff1a;【蚂蚁学python】 【课程链接&#xff1a;【【数据可视化】Python数据图表可视化入门到实战】】 【课程资料链接&#xff1a;【链接】】 Python绘制饼图分析北京天气 饼图&#xff0c;是一个划分为几个扇形的圆形统计图表&#xff…

深入解析Spring Cloud:构建分布式微服务架构的最佳实践

导语&#xff1a;随着互联网业务的快速发展&#xff0c;传统的单体应用已无法满足高并发、高可用、可扩展的需求。微服务架构以其轻量级、独立性、灵活性的特点&#xff0c;逐渐成为大型分布式系统的首选架构。Spring Cloud作为构建微服务架构的重要框架&#xff0c;为开发者提…