(C语言版)力扣(LeetCode)+牛客网(nowcoder)二叉树基础oj练习

在线体验各类最新模型,更有模型 免费Token 额度领取!
立即体验
简介: 如果二叉树每个节点都具有相同的值,那么该二叉树就是单值二叉树。

2ea2116a686e41268028544a249c71f1.png


965. 单值二叉树


题目


如果二叉树每个节点都具有相同的值,那么该二叉树就是单值二叉树。


只有给定的树是单值二叉树时,才返回 true;否则返回 false。


题目链接:单值二叉树


解法


代码如下:


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


首先判定二叉树是否为空,如果为空,直接返回true即可

再判定左右子树是否等值,不等返回false

嵌套递归下一层左右子树

遍历完都没进入条件语句,说明都相等,返回true


100. 相同的树


题目


给你两棵二叉树的根节点 p 和 q ,编写一个函数来检验这两棵树是否相同。


如果两个树在结构上相同,并且节点具有相同的值,则认为它们是相同的。


题目链接:相同的树


解法


代码如下:


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


首先判定两树是否均为空,如果都为空,则返回true

有一个不为空则返回false

都不为空再比较值,不等则返回false

再向下递归遍历左右子树即可。


101. 对称二叉树


题目


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


题目链接对称二叉树


解法


代码如下:


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


这里还是使用递归的写法,由于这个算法需要两个参数实现,所以我们再写一个ret函数来实现,最后返回ret函数返回值即可


和上一题类似,如果树为空,则返回true,后面递归遍历时,是左右对称点比较

第二个条件也是为了后期递归时判断左右对称点是否一个为空,则返回false

第三个条件同理,判断值是否不等,不等则返回false

最后递归左右对称点,遍历整个二叉树。


144. 二叉树的前序遍历


题目


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


题目链接:二叉树的前序遍历


解法


代码如下:


void _preorder(struct TreeNode*root,int* ret,int* returnSize)
{
    if(root==NULL)
        return;
    ret[(*returnSize)++]=root->val;
    _preorder(root->left,ret,returnSize);
    _preorder(root->right,ret,returnSize);
} 
int* preorderTraversal(struct TreeNode* root, int* returnSize){
    int* ret=malloc(sizeof(int)*200);
    *returnSize=0;
    _preorder(root,ret,returnSize);
    return ret;
}


首先我们开辟一个数组空间,题目要求是[0,100],我这里是直接给了200,将returnSize初始化为0

再调用子函数,子函数首先判定结点为空直接不返回值

下面的三个就是关键了

前序遍历是按照二叉树根左右的顺序,所以

先将根节点的值放入数组,在递归遍历左子树,再递归遍历右子树

最后返回数组,结果即为二叉树的前序遍历。


94. 二叉树的中序遍历


题目


给定一个二叉树的根节点 root ,返回 它的 中序 遍历 。


题目链接:二叉树的中序遍历


解法


代码如下:


void _inorder(struct TreeNode*root,int* ret,int* returnSize)
{
    if(root==NULL)
        return;
    _inorder(root->left,ret,returnSize);
    ret[(*returnSize)++]=root->val;
    _inorder(root->right,ret,returnSize);
} 
int* inorderTraversal(struct TreeNode* root, int* returnSize){
    int* ret=malloc(sizeof(int)*200);
    *returnSize=0;
    _inorder(root,ret,returnSize);
    return ret;
}


和上面的题目思路是一样的,只不过中序遍历顺序为左根右

所以我们将子函数稍微调整,先遍历左子树,再记录根节点,最后遍历右子树


145. 二叉树的后序遍历


题目


给你一棵二叉树的根节点 root ,返回其节点值的 后序遍历 。


题目链接:二叉树的后序遍历


解法


代码如下:


void _posorder(struct TreeNode*root,int* ret,int* returnSize)
{
    if(root==NULL)
        return;
    _posorder(root->left,ret,returnSize);
    _posorder(root->right,ret,returnSize);
    ret[(*returnSize)++]=root->val;
} 
int* postorderTraversal(struct TreeNode* root, int* returnSize){
    int* ret=malloc(sizeof(int)*200);
    *returnSize=0;
    _posorder(root,ret,returnSize);
    return ret;
}


和上面的题目思路还是一样的,只不过后序遍历顺序为左右根

所以我们将子函数稍微调整,先遍历左子树,再遍历右子树,最后记录根节点


572. 另一棵树的子树


题目


给你两棵二叉树 root 和 subRoot 。检验 root 中是否包含和 subRoot 具有相同结构和节点值的子树。如果存在,返回 true ;否则,返回 false 。


二叉树 tree 的一棵子树包括 tree 的某个节点和这个节点的所有后代节点。tree 也可以看做它自身的一棵子树。


题目链接:另一棵树的子树


解法


代码如下:


bool check(struct TreeNode* o, struct TreeNode* t)
{
    if (!o && !t) 
        return true;
    if ((o && !t) || (!o && t) || (o->val != t->val)) 
        return false;
    return check(o->left, t->left) && check(o->right, t->right);
}
bool isSubtree(struct TreeNode* o, struct TreeNode* t)
{
    if (!o) 
        return false;
    return check(o, t) || isSubtree(o->left, t) || isSubtree(o->right, t);
}


首先我们判定如果树为空直接返回false

再看下面的返回第一个条件

主树和子树如果都为空则返回true,只有一个为空或则值不相等则返回false

再比较主树的左子树和子树的左子树以及主树的右子树和子树的右子树

遍历完如果相同则为true,如果不同则向左子树再与子树比较,左子树不同再与右子树比较

都不同最后就返回false


KY11 二叉树遍历


题目


编一个程序,读入用户输入的一串先序遍历字符串,根据此字符串建立一个二叉树(以指针方式存储)。 例如如下的先序遍历字符串: ABC##DE#G##F### 其中“#”表示的是空格,空格字符代表空树。建立起此二叉树以后,再对二叉树进行中序遍历,输出遍历结果。


题目链接:二叉树遍历


解法


代码如下:


#include <stdio.h>
typedef struct TreeNode
{
        int* val;
        struct TreeNode* left;
        struct TreeNode* right;
}TreeNode;
TreeNode* creatTree(char* s,int* count)
{
        if(s[*count]=='#'||s[*count]=='\0')
                return NULL;
        TreeNode* newtree = malloc(sizeof(TreeNode));
        newtree->val=s[(*count)++];
        newtree->left=creatTree(s,count);
        (*count)++;
        newtree->right=creatTree(s,count);
        return newtree;
}
void inorder(TreeNode* root)
{
        if(root==NULL)
                return;
        inorder(root->left);
        printf("%c ",root->val);
        inorder(root->right);
}
int main() {
    char s[200];
    scanf("%s",&s);
    int count=0;
    TreeNode* root=creatTree(s,&count);
    inorder(root);
    return 0;
}


首先是二叉树结构体的建立

包含值val和左右子树节点

然后是建二叉树,分别有输入值的字符串数组和初始化下标0两个参数

如果该元素为#或者\0则直接返回空即可

上述条件语句不执行则创建节点,根据二叉树前序遍历的顺序,先输入根的值,再遍历左子树,最后遍历右子树

然后是中序输出函数,节点为空,直接返回,

不执行上述条件语句,则按中序输出顺序,先遍历左子树节点,再输出根节点,最后遍历右子树节点

再看主函数

根据题意不超过100个字符,这里我直接给了200空间

然后就是输入字符串,初始化count为0,为了记录下标

最后调用建树和中序输出两个函数即可


结语


这里的解法代码部分来自力扣官方和作者自己的解法,作者只是进行了详细的剖析和部分改动方便大家理解和提升自己,学会多角度观察问题,解决问题。


有兴趣的小伙伴可以关注作者,如果觉得内容不错,请给个一键三连吧,蟹蟹你哟!!!

制作不易,如有不正之处敬请指出

感谢大家的来访,UU们的观看是我坚持下去的动力

在时间的催化剂下,让我们彼此都成为更优秀的人吧!!!

ac1e53e8c4dd4f1690801bb4dd0f67f7.png

相关文章
|
Go 开发者 索引
【LeetCode 热题100】路径与祖先:二叉树中的深度追踪技巧(力扣33 / 81/ 153/154)(Go语言版)
本文深入探讨了LeetCode中四道关于「搜索旋转排序数组」的经典题目,涵盖了无重复和有重复元素的情况。通过二分查找的变形应用,文章详细解析了每道题的解题思路和Go语言实现代码。关键点包括判断有序区间、处理重复元素以及如何缩小搜索范围。文章还总结了各题的异同,并推荐了类似题目,帮助读者全面掌握二分查找在旋转数组中的应用。无论是初学者还是有经验的开发者,都能从中获得实用的解题技巧和代码实现方法。
552 14
|
Go
【LeetCode 热题100】DP 实战进阶:最长递增子序列、乘积最大子数组、分割等和子集(力扣300 / 152/ 416 )(Go语言版)
本文深入解析三道经典的动态规划问题:**最长递增子序列(LIS)**、**乘积最大子数组** 和 **分割等和子集**。 - **300. LIS** 通过 `dp[i]` 表示以第 `i` 个元素结尾的最长递增子序列长度,支持 O(n²) 动态规划与 O(n log n) 的二分优化。 - **152. 乘积最大子数组** 利用正负数特性,同时维护最大值与最小值的状态转移方程。 - **416. 分割等和子集** 转化为 0-1 背包问题,通过布尔型 DP 实现子集和判断。 总结对比了三题的状态定义与解法技巧,并延伸至相关变种问题,助你掌握动态规划的核心思想与灵活应用!
509 1
|
分布式计算 算法 Go
【LeetCode 热题100】BFS/DFS 实战:岛屿数量 & 腐烂的橘子(力扣200 / 994 )(Go语言版)
本文讲解了两道经典的图论问题:**岛屿数量(LeetCode 200)** 和 **腐烂的橘子(LeetCode 994)**,分别通过 DFS/BFS 实现。在“岛屿数量”中,利用深度或广度优先搜索遍历二维网格,标记连通陆地并计数;“腐烂的橘子”则采用多源 BFS,模拟腐烂传播过程,计算最短时间。两者均需掌握访问标记技巧,是学习网格搜索算法的绝佳实践。
548 1
|
算法 Go
【LeetCode 热题100】深入理解二叉树结构变化与路径特性(力扣104 / 226 / 114 / 543)(Go语言版)
本博客深入探讨二叉树的深度计算、结构变换与路径分析,涵盖四道经典题目:104(最大深度)、226(翻转二叉树)、114(展开为链表)和543(二叉树直径)。通过递归与遍历策略(前序、后序等),解析每题的核心思路与实现方法。结合代码示例(Go语言),帮助读者掌握二叉树相关算法的精髓。下一讲将聚焦二叉树构造问题,欢迎持续关注!
418 10
|
存储 算法 数据可视化
【二叉树遍历入门:从中序遍历到层序与右视图】【LeetCode 热题100】94:二叉树的中序遍历、102:二叉树的层序遍历、199:二叉树的右视图(详细解析)(Go语言版)
本文详细解析了二叉树的三种经典遍历方式:中序遍历(94题)、层序遍历(102题)和右视图(199题)。通过递归与迭代实现中序遍历,深入理解深度优先搜索(DFS);借助队列完成层序遍历和右视图,掌握广度优先搜索(BFS)。文章对比DFS与BFS的思维方式,总结不同遍历的应用场景,为后续构造树结构奠定基础。
667 10
|
Go 索引 Perl
【LeetCode 热题100】【二叉树构造题精讲:前序 + 中序建树 & 有序数组构造 BST】(详细解析)(Go语言版)
本文详细解析了二叉树构造的两类经典问题:通过前序与中序遍历重建二叉树(LeetCode 105),以及将有序数组转化为平衡二叉搜索树(BST,LeetCode 108)。文章从核心思路、递归解法到实现细节逐一拆解,强调通过索引控制子树范围以优化性能,并对比两题的不同构造逻辑。最后总结通用构造套路,提供进阶思考方向,帮助彻底掌握二叉树构造类题目。
946 9
|
Go
【LeetCode 热题100】路径与祖先:二叉树中的深度追踪技巧(力扣437 / 236 )(Go语言版)
本文深入探讨二叉树中路径与祖先问题,涵盖两道经典题目:LeetCode 437(路径总和 III)和236(最近公共祖先)。对于路径总和 III,文章分析了双递归暴力解法与前缀和优化方法,后者通过哈希表记录路径和,将时间复杂度从O(n²)降至O(n)。在最近公共祖先问题中,采用后序遍历递归查找,利用“自底向上”的思路确定最近公共祖先节点。文中详细解析代码实现与核心要点,帮助读者掌握深度追踪技巧,理解树结构中路径与节点关系的本质。这类问题在面试中高频出现,掌握其解法意义重大。
340 4
|
存储 C语言
c语言——二叉树
二叉树的概念在这里就不进行过多的赘述,那么主要说一下我认为重要的部分,第一点就是二叉树里面部分概念的理解:就比如说,你对于如何构建二叉树,掌握的十分深刻,但刷题的时候对于一些题目所给的概念不清楚,导致看不明白题目,这课不好,二叉树的概念如下图所示,其实都很简单,主要是当给他的名字时,你明不明白。还有对于满二叉树与完全二叉树。
330 0
|
Go
【LeetCode 热题100】BFS/DFS 实战:岛屿数量 & 腐烂的橘子(力扣200 / 994 )(Go语言版)
本篇博客详细解析了三道经典的动态规划问题:198. 打家劫舍(线性状态转移)、279. 完全平方数与322. 零钱兑换(完全背包问题)。通过 Go 语言实现,帮助读者掌握动态规划的核心思想及其实战技巧。从状态定义到转移方程,逐步剖析每道题的解法,并总结其异同点,助力解决更复杂的 DP 问题。适合初学者深入理解动态规划的应用场景和优化方法。
358 0
|
算法 Go 索引
【LeetCode 热题100】回溯:括号生成 & 组合总和(力扣22 / 39 )(Go语言版)
本文深入解析了LeetCode上的两道经典回溯算法题:**22. 括号生成**与**39. 组合总和**。括号生成通过维护左右括号数量,确保路径合法并构造有效组合;组合总和则允许元素重复选择,利用剪枝优化搜索空间以找到所有满足目标和的组合。两者均需明确路径、选择列表及结束条件,同时合理运用剪枝策略提升效率。文章附有Go语言实现代码,助你掌握回溯算法的核心思想。
571 0

热门文章

最新文章