首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >二叉树OJ习题

二叉树OJ习题

作者头像
用户11861691
发布2025-10-13 15:13:03
发布2025-10-13 15:13:03
100
代码可运行
举报
运行总次数:0
代码可运行

一. Leetcode 965 单值二叉树

https://leetcode.cn/problems/univalued-binary-tree/description/

思路
  • 若树为空(root 为 NULL),则是单值二叉树,返回 true
  • 若当前节点存在左子节点且左子节点值与当前节点值不同,返回 false
  • 若当前节点存在右子节点且右子节点值与当前节点值不同,返回 false
  • 递归检查左子树和右子树是否都是单值二叉树,只有两者都为单值二叉树时,当前树才是单值二叉树
代码实现
代码语言:javascript
代码运行次数:0
运行
复制
bool isUnivalTree(struct TreeNode* root) {
    //判断节点是否为空
    if(root==NULL)
    {
        return true;
    }
    //左孩子存在并且值不等于其父节点值时,返回false
    if(root->left && root->left->val != root->val)
    {
        return false;
    }
    //右孩子存在并且值不等于其父节点值时,返回false
    if(root->right && root->right->val != root->val)
    {
        return false;
    }
    //递归左右子树,只有都为单值二叉树时,返回false
    return isUnivalTree(root->left) && isUnivalTree(root->right);
}

二. Leetcode 100 相同的树

https://leetcode.cn/problems/same-tree/description/

思路
  • 若两棵树的当前节点都为空(p 和 q 均为 NULL),则这两个节点相同,返回 true
  • 若其中一棵树的当前节点为空而另一棵不为空(p 为 NULL 或 q 为 NULL),则说明两树结构不同,返回 false
  • 当两棵树的节点都不为空时,比较当前节点的值是否相同,若不同,则返回false,
  • 递归检查两树的左子节点是否相同,且右子节点是否相同,只有两者都相同时才返回 true,有一个不同就返回false
代码实现
代码语言:javascript
代码运行次数:0
运行
复制
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);
}

三. Leetcode 101 对称二叉树

https://leetcode.cn/problems/symmetric-tree/description/

思路(运用相同二叉树的思想)

利用递归和镜像比较的特性,将对称树判断转化为特殊的两棵树比较问题。

1. 对称二叉树的核心是判断左子树与右子树是否镜像对称

2. 镜像对称的判断通过改造 "相同树" 的逻辑实现:

  • 比较左子树的左节点与右子树的右节点
  • 比较左子树的右节点与右子树的左节点

3. 具体步骤:

  • 若两节点都为空,则返回 true
  • 若其中一节点为空另一不为空,则返回 false
  • 若两节点值不相等,则返回 false
  • 递归检查左子树左节点与右子树右节点、左子树右节点与右子树左节点是否都对称

4. 对原树调用时,只需检查其左子树与右子树是否镜像对称

代码实现
代码语言:javascript
代码运行次数:0
运行
复制
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->right) && isSameTree(p->right,q->left);
}

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

四. Leetcode 572 另一棵树的子树

https://leetcode.cn/problems/subtree-of-another-tree/description/

思路(运用相同二叉树的思想)

判断 subRoot 是否为 root 的子树,即检查 root 中是否存在与 subRoot 完全相同的子树

通过递归遍历主树的每个节点,将每个节点作为子树根节点与目标子树进行比对,一旦找到匹配则返回 true。

递归逻辑:

  • 若当前 root 为空,返回 false(空树不可能包含子树)
  • 若当前 root 节点为根的子树与 subRoot 相同,返回 true
  • 否则递归检查 root 的左子树或右子树是否包含 subRoot

利用 isSameTree 函数(相同二叉树)检查两棵树是否完全相同

  • 两树都为空则相同
  • 只有一树为空则不同
  • 节点值不同则不同
  • 递归比较左右子树是否都相同
代码实现
代码语言:javascript
代码运行次数:0
运行
复制
typedef struct TreeNode TreeNode;
bool isSameTree(TreeNode* p,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(isSameTree(root,subRoot))
    {
        return true;
    }
    return isSubtree(root->left,subRoot) || isSubtree(root->right,subRoot);
}

五. Leetcode 二叉树的遍历

5.1 Leetcode 144 二叉树的前序遍历

https://leetcode.cn/problems/binary-tree-preorder-traversal/description/

思路

通过先获取树的大小来精确分配内存,再利用递归按前序规则遍历并存储节点值,最终返回完整的遍历结果数组。

1.前序遍历顺序为:根节点 → 左子树 → 右子树

2.实现步骤:

  • 先计算二叉树节点总数(用于分配数组空间)
  • 动态开辟数组空间用于存储遍历结果
  • 通过递归函数完成前序遍历
  • 若节点为空则返回
  • 先访问当前节点(将值存入数组)
  • 递归遍历左子树
  • 递归遍历右子树

3.使用指针记录数组填充位置,确保递归过程中正确更新索引

代码实现
代码语言:javascript
代码运行次数:0
运行
复制
 typedef struct TreeNode TreeNode;

//二叉树节点个数
int BinaryTreeSize(TreeNode* root)
{
    if(root==NULL)
    {
        return 0;
    }
    return 1 + BinaryTreeSize(root->left) + BinaryTreeSize(root->right);
}
//前序遍历
//传下标的指针,在递归过程中能够改变
void PreOrder(TreeNode* root,int* arr,int* pi)
{
    if(root==NULL)
    {
        return;
    }
    arr[(*pi)++]=root->val;
    PreOrder(root->left,arr,pi);
    PreOrder(root->right,arr,pi);
}

int* preorderTraversal(struct TreeNode* root, int* returnSize) {
    //*returnSize表示数组元素个数,也就是二叉树节点个数
    *returnSize = BinaryTreeSize(root);
    int* arr=(int*)malloc(sizeof(int)*(*returnSize));
    int i=0;
    PreOrder(root,arr,&i);
    return arr;
}

5.2 Leetcode 94 二叉树的中序遍历

https://leetcode.cn/problems/binary-tree-inorder-traversal/description/

思路

通过先获取树的大小来精确分配内存,再利用递归按中序规则遍历并存储节点值,最终返回完整的遍历结果数组。

1.中序遍历顺序为:左子树 → 根节点 → 右子树

2.实现步骤:

  • 先计算二叉树节点总数(用于分配数组空间)
  • 动态开辟数组空间用于存储遍历结果
  • 通过递归函数完成中序遍历
  • 若节点为空则返回
  • 先递归遍历左子树
  • 访问当前节点(将值存入数组)
  • 递归遍历右子树

3.使用指针记录数组填充位置,确保递归过程中正确更新索引

代码实现
代码语言:javascript
代码运行次数:0
运行
复制
typedef struct TreeNode TreeNode;

//二叉树节点个数
int BinaryTreeSize(TreeNode* root)
{
    if(root==NULL)
    {
      return 0;
    }
    return 1 + BinaryTreeSize(root->left) + BinaryTreeSize(root->right);
}

//传下标的指针,在递归过程中能够改变
void InOrder(TreeNode* root,int* arr,int* pi)
{
      if(root==NULL)
      {
        return;
      }
      InOrder(root->left,arr,pi);
      arr[(*pi)++]=root->val;
      InOrder(root->right,arr,pi);
}

int* inorderTraversal(struct TreeNode* root, int* returnSize) {
    //*returnSize表示数组元素个数,也就是二叉树节点个数
    *returnSize = BinaryTreeSize(root);
    int* arr=(int*)malloc(sizeof(int)*(*returnSize));
    int i=0;
    InOrder(root,arr,&i);
    return arr;
}

5.3 Leetcode 145 二叉树的后序遍历

https://leetcode.cn/problems/binary-tree-postorder-traversal/description/

思路

通过先获取树的大小来精确分配内存,再利用递归按中序规则遍历并存储节点值,最终返回完整的遍历结果数组。

1.中序遍历顺序为:左子树 → 右子树 → 根节点

2.实现步骤:

  • 先计算二叉树节点总数(用于分配数组空间)
  • 动态开辟数组空间用于存储遍历结果
  • 通过递归函数完成后序遍历
  • 若节点为空则返回
  • 先递归遍历左子树
  • 再递归遍历右子树
  • 访问当前节点(将值存入数组)

3.使用指针记录数组填充位置,确保递归过程中正确更新索引

代码实现
代码语言:javascript
代码运行次数:0
运行
复制
typedef struct TreeNode TreeNode;

//二叉树节点个数
int BinaryTreeSize(TreeNode* root)
{
    if(root==NULL)
    {
        return 0;
    }
    return 1 + BinaryTreeSize(root->left) + BinaryTreeSize(root->right);
}

//传下标的指针,在递归过程中能够改变
void PostOrder(TreeNode* root,int* arr,int* pi)
{
    if(root==NULL)
    {
        return;
    }
    PostOrder(root->left,arr,pi);
    PostOrder(root->right,arr,pi);
    arr[(*pi)++] = root->val;
}

int* postorderTraversal(struct TreeNode* root, int* returnSize) {
    //*returnSize表示数组元素个数,也就是二叉树节点个数
    *returnSize=BinaryTreeSize(root);
    int* arr=(int*)malloc(sizeof(int)*(*returnSize));
    //按后序遍历将二叉树中的数据存储在数组
    int i=0;
    PostOrder(root,arr,&i);
    return arr;
}

六. 牛客网 二叉树的构建及遍历

https://www.nowcoder.com/practice/4b91205483694f449f94c179883c1fef

思路

通过递归复用先序遍历的逻辑构建二叉树,再用递归完成中序遍历,清晰映射二叉树的递归特性

1. 数据结构定义:定义二叉树节点结构(含数据域、左子树指针、右子树指针)

2. 节点创建:实现buyNode函数,动态分配节点内存并初始化(数据域赋值,左右指针置空)

3. 二叉树构建(核心):

  • 基于先序遍历字符串递归构建:遇到 '#' 表示空节点,返回 NULL
  • 非 '#' 字符则创建当前节点,递归构建左子树,再递归构建右子树
  • 用指针pi记录当前处理的字符串索引,确保递归中同步推进

4. 中序遍历:递归实现左子树→根节点→右子树的遍历顺序,打印节点数据

5. 主流程:

  • 读取用户输入的先序字符串
  • 调用构建函数生成二叉树
  • 执行中序遍历并输出结果
代码实现
代码语言:javascript
代码运行次数:0
运行
复制
#include <stdio.h>
#include <stdlib.h>

//定义二叉树节点结构
typedef struct BinaryTreeNode{
    char data;
    struct BinaryTreeNode* left;
    struct BinaryTreeNode* right;
}BTNode;

//申请新节点
BTNode* buyNode(char x)
{
    BTNode* newnode=(BTNode*)malloc(sizeof(BTNode));
    if(newnode==NULL)
    {
        perror("malloc fail!");
        exit(1);
    }
    newnode->data=x;
    newnode->left=newnode->right=NULL;

    return newnode;
}

//构建二叉树
BTNode* creatBinaryTree(char* arr,int* pi)
{
    if(arr[*pi]=='#')
    {
        (*pi)++;
        return NULL;
    }
    BTNode* root=buyNode(arr[(*pi)++]);
    root->left=creatBinaryTree(arr, pi);
    root->right=creatBinaryTree(arr, pi);

    return root;
}

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

int main() {
    //输入字符串存储起来
    char arr[100];
    scanf("%s",arr);
    //按前序遍历构建二叉树
    int i=0;
    BTNode* root = creatBinaryTree(arr, &i);
    //中序遍历
    InOrder(root);
    return 0;
}

七. 二叉树选择题

二叉树的性质:

对任意一棵二叉树,如果度为 0 的节点个数为 n0 ,度为 2 的分支节点个数为 n2 ,则有 n0 = n2 + 1

证明上述性质: 假设⼀个二叉树有 a 个度为2的节点, b 个度为1的节点,c 个叶节点,则这个二叉树的边数是 2a+b 另一方面,由于共有 a+b+c 个节点,所以边数等于 a+b+c-1 结合上面两个公式: 2a+b = a+b+c-1 ,即: a = c - 1

二叉树题目:

根据上面二叉树的性质,完成以下题目

1. 某二叉树共有 399 个结点,其中有 199 个度为2的结点,则该二叉树中的叶子结点数为(200)

叶子节点(即度为0的节点)= 199(度为2的节点)+ 1 = 200

2.在具有 2n 个结点的完全二叉树中,叶子结点个数为( n )

  • 完全二叉树由度为2的节点,度为1的节点(完全二叉树中度为1的节点有1个/0个),度为0的节点组成
  • 2n = n0(度为0的节点) + n1(度为1的节点) + n2(度为2的节点)
  • 2n = n0 + n1 + (n0 - 1)
  • 若n1 == 0:2n = 2n0 - 1 ,n0为分数,不可能
  • 若n1 == 0:2n = 2n0 ,n0 = n

3.⼀棵完全二叉树的结点数位为531个,那么这棵树的高度为( 10 )

总结点个数 n = 2 ^h - 1

当 h = 9 时,最接近531,同时也比532小,所以高度为 10

4.⼀个具有767个结点的完全二叉树,其叶子结点个数为(384)

如果用上一题的思路 n = 2 ^h - 1

当 h = 9 时,最接近767,同时也比767小,767-511=256,这种方法是错误的,因为完全二叉树出了最后一层为叶子节点外,最后一层的上一层仍有叶子节点。

  • n0+n1+n2=767
  • 2n0+n1=768
  • 若n1 = 1,n0为分数,不成立
  • 若n1 = 0,n0=384

链式结构二叉树题目

1.某完全二叉树按层次输出(同⼀层从左到右)的序列为 ABCDEFGH 。该完全二叉树的前序序列为 ABDHECFG

2.二叉树的先序遍历和中序遍历如下:先序遍历:EFHIGJK;中序遍历:HFIEJKG.则二叉树根结点为 E

前序遍历第一个节点即为该二叉树根节点,在它左边的节点为它的左子树,右边为右子树

3.设⼀课二叉树的中序遍历序列:badce,后序遍历序列:bdeca,则二叉树前序遍历序列为ABCDE

后续遍历最后一个节点即为该二叉树根节点,在它左边的节点为它的左子树,右边为右子树

4.某二叉树的后序遍历序列与中序遍历序列相同,均为 ABCDEF ,则按层次输出(同⼀层从左到右)的序列 ABCDEF

前序遍历根节点有边第一个节点为左子树根节点

后序遍历根节点左边第一个节点为右子树根节点


总结

本文围绕二叉树 OJ 习题展开,涵盖了单值二叉树、相同二叉树、对称二叉树、子树判断及遍历等经典问题。通过递归等核心思想,解析了各题的解题思路与实现逻辑,帮助读者掌握二叉树的特性及常见操作,为应对同类问题提供了清晰的思路与方法。

如果大家在练习中发现新的解题角度,或是有没搞懂的知识点,欢迎在评论区留言讨论。后续我也会持续更新数据结构相关的 OJ 解析,咱们一起在刷题中夯实基础,稳步进阶!

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2025-09-02,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一. Leetcode 965 单值二叉树
    • 思路
    • 代码实现
  • 二. Leetcode 100 相同的树
    • 思路
    • 代码实现
  • 三. Leetcode 101 对称二叉树
    • 思路(运用相同二叉树的思想)
      • 代码实现
  • 四. Leetcode 572 另一棵树的子树
    • 思路(运用相同二叉树的思想)
      • 代码实现
  • 五. Leetcode 二叉树的遍历
    • 5.1 Leetcode 144 二叉树的前序遍历
      • 思路
      • 代码实现
    • 5.2 Leetcode 94 二叉树的中序遍历
      • 思路
      • 代码实现
    • 5.3 Leetcode 145 二叉树的后序遍历
      • 思路
      • 代码实现
  • 六. 牛客网 二叉树的构建及遍历
    • 思路
    • 代码实现
  • 七. 二叉树选择题
    • 二叉树的性质:
    • 二叉树题目:
  • 总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档