二叉树OJ

前言、

我们在做二叉树OJ题时,需要注意的点

1、大多数情况下需要用递归解决

2、递归函数的参数选择

3、选择哪种遍历方式递归

4、递归的结束条件是什么

5、递归的返回值

如果在遇到比较难的递归问题,我们一定要多画递归展开图,画图过程中能帮助我们更好的理解递归的返回流程。

树的节点:

复制代码
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */

一、二叉树的最大深度

题目介绍:

解题思路:我们采用前序遍历的方式进行递归运算,我们只需要找到左子树和右子树相对较跟节点更深的节点加一就可以。

题解代码:

复制代码
int maxDepth(struct TreeNode *root) 
{
    if (root == NULL) return 0;
    return fmax(maxDepth(root->left), maxDepth(root->right)) + 1;
}

二、单值二叉树

题目介绍:

解题思路:我们采用后序遍历的方式进行递归运算,我们判断一个树是否是单值二叉树,只需要判断每个子树的左右节点的值和根节点的知否相同,如果不同返回false,否则继递归,直到整棵树都递归完。

复制代码
bool isUnivalTree(struct TreeNode* root)
{
    if(root==NULL)
    {
        return true;
    }
    //判断左数
    if(root->left!=NULL)
    {
        if(root->left->val!=root->val)
        {
            return false;
        }
    }
    //判断右树
    if(root->right!=NULL)
    {
        if(root->right->val!=root->val)
        {
            return false;
        }
    }

    //递归每个节点
    return isUnivalTree(root->left)&&isUnivalTree(root->right);
}

三、二叉树的前序遍历

题目介绍:

解题思路:我们需要先知道前序遍历指先便利根节点,其次是左孩子结点和右孩子节点,对于这道题来说,我们需要创建一个数组,来存放根节点的值。数组的大小为这棵树节点的个数。这下我们就一一解决这个问题:

1、节点的个数:

2、根节点存放在数组中

3、先序递归整个数组

注意:这里我们必须穿的是 i 的地址,因为形参只是形参的一个临时拷贝,每次递归都会传一个 i 而这其中每个函数的 i 互不影响,显然这不是我么不你想要的结果,我们想要的是这些递归函数公用一个 i 。所以我们需要传 i 的地址。

四、中序遍历和后序遍历

题目介绍:

解题思路:之所以把这两道题放在一起是因为他们可以说是,和上面一道题是一毛一样。

只是我们只需要将根节点放入数组这个步骤的位置有所变化:

中序遍历:先左子树递归,在根节点放入数组,在右子树递归。

后序遍历:先左子树递归,在右子树递归,最后将根节点放入数组。

题解代码(二叉树的中序遍历):

复制代码
int TreeSize(struct TreeNode* root)
{
    if(root==NULL)
    {
        return 0;
    }
    return TreeSize(root->left)+TreeSize(root->right)+1;
}
void InOrder(struct TreeNode* root,int*a,int*i)
{
    if(root==NULL)
    {
        return;
    }
    InOrder(root->left,a,i);
    a[*i]=root->val;
    (*i)++;
    InOrder(root->right,a,i);
}

int* inorderTraversal(struct TreeNode* root, int* returnSize)
{
    int size=TreeSize(root);
    int*a=(int*)malloc(sizeof(int)*size);
    *returnSize=size;
    int i=0;
    InOrder(root,a,&i);
    return a;
}

题解代码(二叉树的后序遍历):

复制代码
int TreeSize(struct TreeNode* root)
{
    if(root==NULL)
    {
        return 0;
    }
    return TreeSize(root->left)+TreeSize(root->right)+1;
}
void PostOrder(struct TreeNode* root,int*a,int*i)
{
    if(root==NULL)
    {
        return;
    }
    PostOrder(root->left,a,i);
    PostOrder(root->right,a,i);
    a[*i]=root->val;
    (*i)++;
}
int* postorderTraversal(struct TreeNode* root, int* returnSize)
{
    int size=TreeSize(root);
    int*a=(int*)malloc(sizeof(int)*size);
    *returnSize=size;
    int i=0;
    PostOrder(root,a,&i);
    return a;
}

五、相同的树

题目介绍:

解题思路:我们只需要判断两棵树的每个节点都相同便可以知道他们是相同的树。

遍历顺序:先序遍历。

递归结束条件:root==NULL;

递归参数:q->left p->left 和 q->right p->right

题解代码:

复制代码
bool isSameTree(struct TreeNode* p, struct TreeNode* q)
{
    //两个都为空
    if(p==NULL&&q==NULL)
    {
        return true;
    }
    //其中一个为空
    if(p==NULL||q==NULL)
    {
        return false;
    }

    //两个都不为空
    if(q->val!=p->val)
    {
        return false;
    }

    return isSameTree(q->left,p->left)&&isSameTree(q->right,p->right);
}

六、另一颗子树

题目介绍:

解题思路:

有了 "相同的树 " 题目的铺垫,这道题也就相对简单许多。

我们只需要判断有没有一个子树是和 subRoot相等的。

遍历顺序:先序遍历。

递归结束条件:root==NULL;

递归参数:root->left subRoot 和 root->right 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(p->left,q->left)&&isSameTree(p->right,q->right);
}

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

七、翻转二叉树

题目介绍:

题解思路:

我们需要将二叉树的左右孩子都交换,交换的是树的节点,而不是数节点的值。我们在交换数的节点是需要用到二级指针。

遍历顺序:中序遍历。

递归结束条件:root==NULL;

递归参数: root->left root->right

题解代码:

复制代码
void Swap(struct TreeNode**p1,struct TreeNode**p2)
{
    struct TreeNode*temp=*p1;
    *p1=*p2;
    *p2=temp;
}
struct TreeNode* invertTree(struct TreeNode* root)
{
    if(root==NULL)
    {
        return root;
    }
 
    //中序遍历
    Swap(&root->left,&root->right);
    invertTree(root->left);
    invertTree(root->right);

    return root;
}

八、对称二叉树

题目介绍:

解题思路:我们判断一个二叉树是否对称,换个思路就是在判断这个二叉树的左子树翻转后和右子树是否相等。

遍历顺序:后序遍历。

递归结束条件:

if(left==NULL&&right==NULL)

{

return true;

}

if(left==NULL||right==NULL)

{

return false;

}

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

{

return false;

}

递归参数:struct TreeNode*left struct TreeNode*right

我们需要判断 : 左子树的左孩子是否等于右子树右孩子

左子树的右孩子是否等于右子树的左孩子

题解代码:

复制代码
bool symmetry(struct TreeNode*left,struct TreeNode*right)
{
    if(left==NULL&&right==NULL)
    {
        return true;
    }
    if(left==NULL||right==NULL)
    {
        return false;
    }
    if(left->val!=right->val)
    {
        return false;
    }
    return symmetry(left->left,right->right)&&symmetry(left->right,right->left);

}


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

总结、

二叉树的OJ题这篇博客就讲完了,这些题目都来自 力扣 。大家有什么不懂的问题尽管在评论区里题,我们一起讨论解决。最后还望大家动动小手点赞收藏评论支持支持,你们的支持是我最大的动力,我也会持续向大家输送好文。加油,共勉!!!

相关推荐
吟安安安安4 分钟前
适合短期冲刺的学习工作流(针对算法)
学习·算法
科研前沿9 分钟前
什么是时空融合技术?
大数据·人工智能·数码相机·算法·重构·空间计算
weixin_4217252613 分钟前
C语言常用字符串函数:长度、比较、拼接和查找
c语言·字符串函数·查找·比较·长度
AI科技星14 分钟前
全域数学本源公理:0、1、∞ 三者核心关系 (典籍定稿版)
人工智能·算法·数学建模·数据挖掘·量子计算
AI科技星19 分钟前
全域数学·第卷:场计算机卷(场空间计算机)【乖乖数学】
java·开发语言·人工智能·算法·机器学习·数学建模·数据挖掘
Deepoch21 分钟前
数学模型驱动:Deepoc 低幻觉数学大模型助力发动机全周期智能优化
人工智能·算法·机器学习·deepoc·数学大模型·低幻觉
嘻嘻哈哈樱桃29 分钟前
牛客经典101题解题集--贪心算法+模拟
java·python·算法·贪心算法
AKDreamer_HeXY30 分钟前
QOJ 12255 - 36 Puzzle 题解
数据结构·c++·数学·算法·icpc·qoj
AI科技星39 分钟前
《全域数学》第一部 数术本源 第三卷 代数原本第14篇 附录二 猜想证明【乖乖数学】
人工智能·算法·数学建模·数据挖掘·量子计算
Wect1 小时前
LeetCode 72. 编辑距离:动态规划经典题解
前端·算法·typescript