二叉树OJ题目合集(单值、对称、平衡、构建加遍历)

news2024/11/25 16:41:34

目录

前言:

一:单值二叉树

二:二叉树遍历

核心点

(1)前序

(2)中序

(3)后序

三:判断两颗树是否相同

四:判断二叉树是否对称

五:判断一颗树是否为另一颗树的子树

六:平衡二叉树

七:二叉树的构建加遍历


前言:

这一部分适合已经适用于已经掌握二叉树基础的同学(遍历,求节点数等)

不清楚的同学可以先看之前一期:

https://blog.csdn.net/2301_76269963/article/details/130231257?spm=1001.2014.3001.5502

一:单值二叉树

题目链接:https://leetcode.cn/problems/univalued-binary-tree/submissions/

题目要求:

基础思路:

(1)首先判断根节点值与左右子树值是否相同,如果不同就返回 false。(注意如果左右子树为空不需要进行判断)

(2)否则,递归判断其左右子树是否为单值二叉树。(空树算作单值二叉树)

(3)如果一直到叶子节点都没有出现不相同的节点值,则返回 true,表示该树为单值二叉树。

(左子树右子树同时为单值树才行)

(这个题目比较简单,不利用递归也可以实现,但是需要建立辅助栈,只要遍历所有节点依次判断,遇到不同返回false,遍历完都没有不同返回true)

代码:

bool isUnivalTree(struct TreeNode* root)
{
    if(root == NULL)
    {
        return true;
    }

    if(root->left!=NULL && root->left->val != root->val)
    {
        return false;
    }

    if(root->right!=NULL && root->right->val != root->val)
    {
        return false;
    }

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

}

图解:

二:二叉树遍历

核心点

(1)我们知道在函数调用时候形参只是实参的临时拷贝,如果我们直接传值调用,是没办法直接与那个变量建立联系的。

(2)如果我们想让函数不管递归深度多大都始终使用一个变量,我们应该进行传址调用

(1)前序

题目链接:https://leetcode.cn/problems/binary-tree-preorder-traversal/submissions/

题目要求:

思路:

①和我们之前的打印不同,这一次遍历是要把节点数据存入数组中

②先求节点数(之前一次讲过),依据节点数来开辟空间

③先存储数据,再递归走左子树,后递归走右子树,每一次存储完成都要让(*i)加1(本体加1)

④记得为(*returnSize)赋值数组元素个数,告知元素个数,别人才能进行测试

代码:

//求树的节点数
int BinaryTreeSize(struct TreeNode* root)
{
	return root == NULL ? 0 :
		BinaryTreeSize(root->left) + BinaryTreeSize(root->right) + 1;
}

void _preorderTraversal(struct TreeNode* root,int* a,int* i)
{
    if(root == NULL)
    {
        return;
    }
    //赋值
    a[*i] = root->val;
    *i+=1;
    //左子树
    _preorderTraversal(root->left,a,i);
    //右子树
    _preorderTraversal(root->right,a,i);
}

int* preorderTraversal(struct TreeNode* root, int* returnSize)
{
    //申请空间存储数据
    int size=BinaryTreeSize(root);
    int* a=(int*)malloc(sizeof(int)*size);

    //遍历存储数据(利用子函数)
    int i=0;
    _preorderTraversal(root,a,&i);

    //返回
    *returnSize = size;
    return a;
}

(2)中序

题目链接:https://leetcode.cn/problems/binary-tree-inorder-traversal/submissions/

题目要求:

思路:与前序基本一致,只是换了存储的顺序

代码:

//求树的节点数
int BinaryTreeSize(struct TreeNode* root)
{
	return root == NULL ? 0 :
		BinaryTreeSize(root->left) + BinaryTreeSize(root->right) + 1;
}

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

int* inorderTraversal(struct TreeNode* root, int* returnSize)
{
    //申请空间存储数据
    int size = BinaryTreeSize(root);
    int* a = (int*)malloc(sizeof(int)*size);
    
    //调用子函数存储
    int i=0;
    _inorderTraversal(root,a,&i);

    //返回
    *returnSize = size;
    return a;
}

(3)后序

题目链接:https://leetcode.cn/problems/binary-tree-postorder-traversal/submissions/

题目要求:

思路:与前序基本一致,只是换了存储的顺序

代码:

//求树的节点数
int BinaryTreeSize(struct TreeNode* root)
{
	return root == NULL ? 0 :
		BinaryTreeSize(root->left) + BinaryTreeSize(root->right) + 1;
}

void _postorderTraversal(struct TreeNode* root,int* a,int* i)
{
    if(root == NULL)
    {
        return;
    }
    //左子树
    _postorderTraversal(root->left,a,i);
    //右子树
    _postorderTraversal(root->right,a,i);
    //存储
    a[*i] = root->val;
    *i += 1;
}

int* postorderTraversal(struct TreeNode* root, int* returnSize)
{
    //申请空间存储
    int size = BinaryTreeSize(root);
    int* a = (int*)malloc(sizeof(int)*size);

    //调用子函数遍历存储
    int i=0;
    _postorderTraversal(root,a,&i);

    //返回
    *returnSize = size;
    return a;
}

三:判断两颗树是否相同

题目链接:https://leetcode.cn/problems/same-tree/submissions/

题目要求:

基础思路:

(1)先判断节点地址,如果两边都为空返回true,一边为空一边不为空返回false

(2)然后判断根部数据是否相同,不同返回false

(3)否则递归判断左子树和右子树是否相同

(4)除了根部以外,左右子树都相同两棵树才相同

代码:

bool isSameTree(struct TreeNode* p, struct TreeNode* q)
{
    if(p == NULL && p==q)
    {
        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);
}

四:判断二叉树是否对称

题目链接:https://leetcode.cn/problems/symmetric-tree/submissions/

题目要求:

基础思路:

(1)和前面判断两棵树是否相同很相似,这里相当于把左右子树当成1树和2树

(2)先判断节点地址,如果两边都为空返回true,一边为空一边不为空返回false

(3)先比较根部是否相同,不同返回false

(4)根部相同,递归判断1树左子树与2树右子树是否相同,1树右子树与2树左子树是否相同

(5)到叶子节点依然相同,说明这颗树轴对称

代码:

bool CheckSymmetry(struct TreeNode* left,struct TreeNode* right)
{
    //如果都为空,对称
    if(left == NULL && left == right)
    {
        return true;
    }
    //一方为空一方不为,不对称
    if(left == NULL || right == NULL)
    {
        return false;
    }

    if(left->val != right->val)
    {
        return false;
    }

    return CheckSymmetry(left->left,right->right) 
        && CheckSymmetry(left->right,right->left);
}


bool isSymmetric(struct TreeNode* root)
{
    //利用子函数判断是否对称
    return CheckSymmetry(root->left,root->right);
}

五:判断一颗树是否为另一颗树的子树

题目链接:https://leetcode.cn/problems/subtree-of-another-tree/

题目要求:

基础思路:

(1)大致思路就是拿母树的每一个子树依次和subRoot比较

有相同的返回true,否则返回false

(2)如果母树为空,返回false

(3)利用前面判断两棵树是否相同的函数,我们先判断母树与subRoot是否相同

(4)相同返回true,不同就递归走母树的左子树和右子树

(5)左右子树只要有一方相同就为true

代码:

//判断两颗树是否相同
bool isSameTree(struct TreeNode* p, struct TreeNode* q)
{
    if(p == NULL && p==q)
    {
        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 == NULL)
    {
        return false;
    }

    if(isSameTree(root,subRoot))
    {
        return true;
    }

    return isSubtree(root->left,subRoot) 
        || isSubtree(root->right,subRoot);
}

图解:


六:平衡二叉树

题目链接:https://leetcode.cn/problems/balanced-binary-tree/

题目要求:

 基础思路:

(1)节点为空返回true(空树也是平衡二叉树)

(2)利用函数(之前讲过)计算当前节点的左右子树的高度差

(3)如果高度差不超过 1,则递归判断其左右子树是否为平衡二叉树

(4)如果有任何一个节点的左右子树的高度差大于 1,则该树不是平衡二叉树

代码:

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

	if (root->left == NULL && root->right == NULL)
	{
		return 1;
	}

	return fmax(BinaryTreeDepth(root->left), BinaryTreeDepth(root->right)) + 1;
}

bool isBalanced(struct TreeNode* root)
{
    if(root == NULL)
        return true;

    int leftDepth = BinaryTreeDepth(root->left);
    int rightDepth = BinaryTreeDepth(root->right);
    
    return abs(leftDepth-rightDepth)>1?false:
    isBalanced(root->left)&&isBalanced(root->right);
}

七:二叉树的构建加遍历

题目链接:https://www.nowcoder.com/practice/4b91205483694f449f94c179883c1fef?tpId=0&difficulty=&judgeStatus=&tags=&title=%E4%BA%8C%E5%8F%89%E6%A0%91&sourceUrl=&gioEnter=menu

题目要求:

基础思路:

(1)依据输入的字符串建树(递归)

①创建的顺序是先左子树后右子树

②为了确保递归过程中使用同一个变量,我们传下标的地址

如果字符为'#'或者'\0'(字符串走到空),节点地址赋值为空

返回创建好的树的根部节点地址

图解:

 

(2)进行中序遍历(之前讲过,不赘述)

代码:

#include <stdio.h>
#include <stdlib.h>

typedef char BTDataType;

typedef struct BinaryTreeNode
{
	//存储左孩子的地址
	struct BinaryTreeNode* left;
	//存储右孩子的地址
	struct BinaryTreeNode* right;
	BTDataType data;
}BTNode;

BTNode* maketree(char*arr,int* i)
{
    if(arr[*i]=='#'||arr[*i]=='\0')
    {
        return NULL;
    }
    BTNode* newnode = (BTNode*)malloc(sizeof(BTNode));
    newnode->data = arr[(*i)++];
     
    newnode->left = maketree(arr,i);
    //这里加1是因为字符为'#'时候直接返回了空
    //我们要走到下一个字符就要进行自加
    (*i)++;
    newnode->right = maketree(arr,i);
    return newnode;
}

//中序遍历
void InOrder(BTNode* root)
{
    if(root == NULL)
    {
        return;
    }
	
	//左树
	InOrder(root->left);
	//打印
	printf("%c ", root->data);
	//右树
	InOrder(root->right);
}

int main() 
{
    //字符串长度不超过100
    char str[100]= {0};

    //可能有多组输入   
    while(scanf("%s",str) != EOF)
    {
        //建树
        int i = 0;
        BTNode* root = maketree(str,&i);

        //遍历
        InOrder(root);
    }

    return 0;
}

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

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

相关文章

创建的django项目生成后,没有默认的数据库生成

目录 1、尚未执行迁移 1.1 首先&#xff0c;在setting.py文件中配置数据库链接 1.2 确保在Terminal运行已经执行了如下命令来创建数据库表格。 1.3 在数据库刷新就有了 2、已经使用了自定义的数据库 3、尚未配置默认数据库 1、尚未执行迁移 1.1 首先&#xff0c;在setting.…

介绍一款优秀的网址导航,可以部署到自己公司内部:hexo-theme-webstack

GitHub - HCLonely/hexo-theme-webstack: A hexo theme based on webstack. | 一个基于webstack的hexo主题。 中文文档 A Hexo theme based on WebStackPage. Installation hexo > 4.0 git clone https://github.com/HCLonely/hexo-theme-webstack themes/webstack hexo …

C++中的stack容器

文章目录 stack的介绍stack的使用 stack的介绍 stack是一种容器适配器&#xff0c;专门用在具有后进先出操作特性的环境中&#xff0c;只能在容器的一端进行插入删除&#xff1b;stack是作为容器适配器被实现的&#xff0c;容器适配器即是对特性类封装作为其底层的容器&#xf…

101-Linux_I/O复用方法之select

文章目录 1.select系统调用的作用2.select系统调用的原型3.集合fdset4.使用select实现TCP服务器(1)服务器端代码:(2)客户端代码(3)运行结果截图 1.select系统调用的作用 在一段指定时间内&#xff0c;监听用户感兴趣的文件描述符的可读、可写和异常等事件 2.select系统调用的…

Typora Markdown 中 LaTeX 公式居左、对齐的方法

我们知道公式块里的公式默认是居中的&#xff0c;我们想让公式居左&#xff08;顶着左页面&#xff09;可以使用如下格式的 flalign 数学环境&#xff1a; 不多说&#xff0c;先看示例 示例 \begin{flalign} &\iint_D\frac{\sin y}{y}{\rm d}\sigma\\ &\int_0^1{\rm…

【redis】redis分布式锁(二)可重入锁+设计模式

【redis】redis分布式锁&#xff08;二&#xff09;可重入锁 文章目录 【redis】redis分布式锁&#xff08;二&#xff09;可重入锁前言一、可重入锁&#xff08;又名递归锁&#xff09;1、说明&#xff1a;2、分开解释&#xff1a;3、可重入锁的种类隐式锁&#xff08;即synch…

Nautilus Chain 测试网第二阶段,推出忠诚度计划及广泛空投

随着更多的公链底层面向市场&#xff0c;通过参与早期测试在主网上线后获得激励成为了行业的一个热点话题&#xff0c;在Apots、Arbitrum One、Optimism等陆续发放了测试空投后&#xff0c;以Layer3为主要特性的Nautilus Chain也在前不久明确表示将会有空投&#xff0c;引发行业…

《嵌入式系统》知识总结3:STM32微控制器

STM32系列产品命名规则 以stm32f103zet6为例 Stm32微控制器架构 模块 • 处理器核心 • 存储器 • 时钟电路、系统总线 • 外设&#xff08;硬件单元&#xff09;&#xff1a;I/O接口、通信接口、定时器 、ADC和DAC&#xff0c; …… 系统结构 哈佛存储结构 • 独立的…

mockjs学习笔记

文章目录 一、什么是mockjs二、安装mockj项目安装mock 三、mock语法生成字符串生成文本生成标题和句子生成段落生成数字生成自增id生成姓名-地址-身份证随机生成图片生成时间 mock拦截请求定义get请求定义post请求 四、实现新闻管理案例获取数据添加新闻删除新闻 一、什么是moc…

有趣的地理题

题目 总部位于上海的“哔哩哔哩”&#xff08;简称B站&#xff09;&#xff0c;是国内知名的视频网站。在B站投稿的用户被称为“UP主”。据统计&#xff0c;B站的UP主群体中&#xff0c;来自上海的比例最高&#xff0c;200万粉丝以上的UP主&#xff0c;来自上海的比例超过 30 …

最佳Midjourney动漫相关风格提示词,值得收藏

先补充概念&#xff0c;后面慢慢补图片咯 动漫艺术家 下面是一些最伟大的艺术家的名单 Hayao Miyazaki, Co-founder of Studio Ghibli&#xff08;宫崎骏&#xff0c;吉卜力工作室的共同创始人&#xff09;Eiichiro Oda, One Piece&#xff08;织田荣一郎&#xff0c;《海贼…

【Linux】Linux下常见基本指令

&#x1f331;博客主页&#xff1a;大寄一场. &#x1f331;系列专栏&#xff1a;Linux &#x1f618;博客制作不易欢迎各位&#x1f44d;点赞⭐收藏➕关注 目录 前言 一、文件和目录操作指令 ls指令 pwd指令 cd指令 touch指令 rmdir指令 && rm 指令&#xff1a; man指…

吉布斯采样方法

吉布斯采样方法 对于多元分布, P ( X ) , X [ x 1 x 2 ] P(X), X\left[\begin{array}{l} x_1 \\ x_2 \end{array}\right] P(X),X[x1​x2​​]吉布斯抽样执行如下。假设很难从联合分布中抽样 P ( x 1 , x 2 ) P\left(x_1, x_2\right) P(x1​,x2​)但是从条件分布 P ( x 1 ∣ …

一键轻松拥有自己专属的 ChatGPT 网页版,搭建一个私人的可随时随地访问的ChatGPT网站

前言 ChatGPT是一种基于Transformer架构的自然语言处理模型&#xff0c;由OpenAI开发。GPT是“Generative Pre-trained Transformer”的缩写&#xff0c;意为“预训练生成式Transformer模型”。 ChatGPT模型是一种无监督学习模型&#xff0c;它可以在大规模文本数据上进行预训…

scratch比大小 中国电子学会图形化编程 少儿编程 scratch编程等级考试三级真题和答案解析2023年3月

目录 scratch比大小 一、题目要求 1、准备工作 2、功能实现 二、案例分析

【react从入门到精通】深入理解React生命周期

文章目录 前言React技能树React的生命周期是什么React v16.0前的生命周期组件初始化(initialization)阶段组件挂载(Mounting)阶段组件更新(update)阶段组件销毁阶段 React v16.4 的生命周期总结写在最后 前言 在上一篇文章《react入门这一篇就够了》中我们已经掌握了React的基本…

软件STM32cubeIDE下STM32F1xx和STM32F4xx使用:备份寄存器+复位标志位-基础样例

软件STM32cubeIDE下STM32F1xx和STM32F4xx使用&#xff1a;备份寄存器复位标志位-基础样例 1、前言2 、 实验环境3、自我总结&#xff08;1&#xff09;对于备份寄存器&#xff08;BKP&#xff09;:&#xff08;2&#xff09;对于复位标志位&#xff08;RCC_CSR&#xff09;&…

【5G RRC】RSRP、RSRQ以及SINR含义、计算过程详细介绍

博主未授权任何人或组织机构转载博主任何原创文章&#xff0c;感谢各位对原创的支持&#xff01; 博主链接 本人就职于国际知名终端厂商&#xff0c;负责modem芯片研发。 在5G早期负责终端数据业务层、核心网相关的开发工作&#xff0c;目前牵头6G算力网络技术标准研究。 博客…

一道经典的小学数学题,和它背后的贪心算法(35)

小朋友们好&#xff0c;大朋友们好&#xff01; 我是猫妹&#xff0c;一名爱上Python编程的小学生。 欢迎和猫妹一起&#xff0c;趣味学Python。 今日主题 这个五一小长假&#xff0c;你玩得怎么样&#xff1f; 今天&#xff0c;咱们先做一道经典的小学数学题&#xff0c;…

Enabling Fast and Universal Audio Adversarial Attack Using Generative Model

Enabling Fast and Universal Audio Adversarial Attack Using Generative Model https://www.winlab.rutgers.edu/~yychen/ AAAI 2021 文章目录 Enabling Fast and Universal Audio Adversarial Attack Using Generative ModelAbstractIntroductionLimitations of Prior WorkT…