二叉树面试题(C 语言)

news2024/12/28 3:02:00

目录

  • 1. 单值二叉树
  • 2. 相同的树
  • 3. 对称二叉树
  • 4. 二叉树的前序遍历
  • 5. 二叉树的中序遍历
  • 6. 二叉树的后序遍历
  • 7. 另一颗树的子树
  • 8. 通过前序遍历返回中序遍历

1. 单值二叉树

题目描述: 如果二叉树每个节点都具有相同的值,那么该二叉树就是单值二叉树。只有给定的树是单值二叉树时,才返回 true;否则返回 false。

示例 1:
在这里插入图片描述
输入:[1,1,1,1,1,null,1]
输出:true

示例 2:
在这里插入图片描述
输入:[2,2,2,5,2]
输出:false

提示:

  1. 给定树的节点数范围是 [1, 100]。
  2. 每个节点的值都是整数,范围为 [0, 99]

题目OJ链接: link

解题思路: 运用递归的思想,把二叉树分成一个个小树。根节点和左右孩子比较,若相同则左右孩子继续和它们的孩子比较,直到空树。遇到空树需要返回 true,因为遇到空树了就证明你这一整棵树都满足单值条件。其中有一组不相同就返回 false,全部相同返回 true。

代码如下:

bool isUnivalTree(struct TreeNode* root) {
    // 空树
    if (NULL == root)
        return true;
    // 根节点和孩子比较
    if (root->left && root->left->val != root->val)
        return false;
    if (root->right && root->right->val != root->val)
        return false;
    // 继续比较左子树和右子树
    return isUnivalTree(root->left)
        && isUnivalTree(root->right);
}

2. 相同的树

题目描述: 给你两棵二叉树的根节点 p 和 q ,编写一个函数来检验这两棵树是否相同。如果两个树在结构上相同,并且节点具有相同的值,则认为它们是相同的。

示例 1:
在这里插入图片描述
输入:p = [1,2,3], q = [1,2,3]
输出:true

示例 2:
在这里插入图片描述
输入:p = [1,2], q = [1,null,2]
输出:false

示例 3:
在这里插入图片描述
输入:p = [1,2,1], q = [1,1,2]
输出:false

提示:

  1. 两棵树上的节点数目都在范围 [0, 100] 内
  2. -104 <= Node.val <= 104

题目OJ链接: link

解题思路: 首先判断根节点,然后再判断左子树,再判断右子树,直到两边都是空树。全部都满足才是相同的树,返回 true;一个地方不满足都是不相同的树,返回 false。

代码如下:

bool isSameTree(struct TreeNode* p, struct TreeNode* q) {
    // 空树判断
    if (NULL == p && NULL == q)
        return true;
    // 有一颗空树
    if (NULL == p || NULL == q)
        return false;
    // 根节点不同
    if (p->val != q->val)
        return false;
    // 左右子树
    return isSameTree(p->left, q->left)
        && isSameTree(p->right, q->right);
}

3. 对称二叉树

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

示例 1:
在这里插入图片描述
输入:root = [1,2,2,3,4,4,3]
输出:true

示例 2:
在这里插入图片描述
输入:root = [1,2,2,null,3,null,3]
输出:false

提示:

  1. 树中节点数目在范围 [1, 1000] 内
  2. -100 <= Node.val <= 100

题目OJ链接: link

解题思路: 对称二叉树根节点的左右子树对称,那么左子树的左子树应该和右子树的右子树对称,左子树的右子树应该和右子树的左子树对称。直到两边都是空树,返回 true。只要有一个不满足,就返回 false。

代码如下:

typedef struct TreeNode TreeNode;

// 左右子树对称判断
bool isSymmetricLeftAndRight(TreeNode* left, TreeNode* right)
{
    // 都是空树
    if (NULL == left && NULL == right)
        return true;
    // 有一颗空树
    if (NULL == left || NULL == right)
        return false;
    // 值不相同
    if (left->val != right->val)
        return false;
    // 对称树比较
    return isSymmetricLeftAndRight(left->left, right->right)
        && isSymmetricLeftAndRight(left->right, right->left);
}

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

4. 二叉树的前序遍历

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

示例 1:

输入:root = [1,null,2,3]

输出:[1,2,3]

解释:
在这里插入图片描述

示例 2:

输入:root = [1,2,3,4,5,null,8,null,null,6,7,9]

输出:[1,2,4,5,6,7,3,8,9]

解释:
在这里插入图片描述

示例 3:

输入:root = []

输出:[]

示例 4:

输入:root = [1]

输出:[1]

提示:

  1. 树中节点数目在范围 [0, 100] 内
  2. -100 <= Node.val <= 100

题目OJ链接: link

解题思路: 本题需要动态开辟一个数组用来存储二叉树的前序遍历进行返回,第二个参数需要返回开辟数组的大小。第一步需要计算二叉树的节点个数,然后再开辟空间,返回二叉树的前序遍历。

代码如下:

typedef struct TreeNode TreeNode;

// 返回二叉树节点的个数
size_t TreeSize(TreeNode* root)
{
    // 空树
    if (NULL == root)
        return 0;
    // 返回 1+左右节点的个数
    return 1 + TreeSize(root->left) + TreeSize(root->right);
}

// 记录二叉树的前序遍历
void GetPreOrder(TreeNode* root, int* arr, int* pi)
{
    // 空树
    if (NULL == root)
        return;
    // 记录根节点
    arr[(*pi)] = root->val;
    ++(*pi);
    // 记录左子树
    GetPreOrder(root->left, arr, pi);
    // 记录右子树
    GetPreOrder(root->right, arr, pi);
}

int* preorderTraversal(struct TreeNode* root, int* returnSize) {
    // 获得节点个数
    size_t n = TreeSize(root);
    *returnSize = n;
    // 开辟空间
    int* arr = (int*)malloc(sizeof(int)*n);
    // 获得前序遍历
    int i = 0;
    GetPreOrder(root, arr, &i);
    // 返回
    return arr;
}

5. 二叉树的中序遍历

本题和二叉树的前序遍历相似,只给出题目链接和代码。

题目OJ链接: link

代码如下:

typedef struct TreeNode TreeNode;

// 返回二叉树的节点个数
size_t TreeSize(TreeNode* root)
{
    // 空树
    if (NULL == root)
        return 0;
    // 返回 1 + 左右子树节点个数
    return 1 + TreeSize(root->left) + TreeSize(root->right);
}

// 获得二叉树中序遍历
void GetInOrder(TreeNode* root, int* arr, int* pi)
{
    // 空树
    if (NULL == root)
        return;
    // 左子树
    GetInOrder(root->left, arr, pi);
    // 记录根节点
    arr[*pi] = root->val;
    ++*pi;
    // 右子树
    GetInOrder(root->right, arr, pi);
}

int* inorderTraversal(struct TreeNode* root, int* returnSize) {
    // 获得节点个数
    size_t n = TreeSize(root);
    *returnSize = n;
    // 开辟空间
    int* arr = (int*)malloc(sizeof(int)*n);
    // 获得中序遍历
    int i = 0;
    GetInOrder(root, arr, &i);
    // 返回
    return arr;
}

6. 二叉树的后序遍历

题目OJ链接: link

代码如下:

typedef struct TreeNode TreeNode;

// 返回二叉树节点个数
size_t TreeSize(TreeNode* root)
{
    // 空树
    if (NULL == root)
        return 0;
    // 返回 1 + 左右子树节点个数
    return 1 + TreeSize(root->left) + TreeSize(root->right);
}

// 返回二叉树的后序遍历
void GetPostOrder(TreeNode* root, int* arr, int* pi)
{
    // 空树
    if (NULL == root)
        return;
    // 左子树
    GetPostOrder(root->left, arr, pi);
    // 右子树
    GetPostOrder(root->right, arr, pi);
    // 记录根节点
    arr[*pi] = root->val;
    ++*pi;
}

int* postorderTraversal(struct TreeNode* root, int* returnSize) {
    // 获得节点个数
    size_t n = TreeSize(root);
    *returnSize = n;
    // 开辟对应空间
    int* arr = (int*)malloc(sizeof(int)*n);
    // 获得中序遍历
    int i = 0;
    GetPostOrder(root, arr, &i);
    // 返回
    return arr;
}

7. 另一颗树的子树

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

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

示例 1:
在这里插入图片描述
输入:root = [3,4,5,1,2], subRoot = [4,1,2]
输出:true

示例 2:
在这里插入图片描述
输入:root = [3,4,5,1,2,null,null,null,null,0], subRoot = [4,1,2]
输出:false

提示:

  1. root 树上的节点数量范围是 [1, 2000]
  2. subRoot 树上的节点数量范围是 [1, 1000]
  3. -104 <= root.val <= 104
  4. -104 <= subRoot.val <= 104

题目OJ链接: link

解题思路: 把当前数与之比较,不相同则比较子树,子树按照这个方法继续比较,直到空树。其中有一颗树与之相同就返回 false。

代码如下:

typedef struct TreeNode TreeNode;

// 判断两棵树是否相同
bool isSameTree(TreeNode* root1, TreeNode* root2)
{
    // 都是空树
    if (NULL == root1 && NULL == root2)
        return true;
    // 有一颗空树
    if (NULL == root1 || NULL == root2)
        return false;
    // 值不相同
    if (root1->val != root2->val)
        return false;
    // 左右子树比较
    return isSameTree(root1->left, root2->left)
        && isSameTree(root1->right, root2->right);
}

bool isSubtree(struct TreeNode* root, struct TreeNode* subRoot) {
    // 空树
    if (NULL == root)
        return false;
    // 当前树判断
    if (isSameTree(root, subRoot))
        return true;
    // 左右子树判断
    return isSubtree(root->left, subRoot)
        || isSubtree(root->right, subRoot);
}

8. 通过前序遍历返回中序遍历

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

输入描述:
输入包括1行字符串,长度不超过100。

输出描述:
可能有多组测试数据,对于每组数据, 输出将输入字符串建立二叉树后中序遍历的序列,每个字符后面都有一个空格。 每个输出结果占一行。

示例1
输入:
abc##de#g##f###
输出:
c b e g d f a

题目OJ链接: link

解题思路: 首先根据前序遍历构建出这颗二叉树,先构建根节点然后构建左子树,再构建右子树,如此往复,直到空树。再通过构建的二叉树返回其中序遍历。

代码如下:

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

// 类型声明
typedef char DataType;

// 二叉树节点声明
typedef struct TreeNode
{
    DataType val;
    struct TreeNode* left;
    struct TreeNode* right;
}TreeNode;

// 构建二叉树
TreeNode* CreateTree(char* tmp, int* pi)
{
    // 空树
    if ('#' == tmp[*pi])
    {
        ++(*pi);
        return NULL;
    }
    // 构建根节点
    TreeNode* root = (TreeNode*)malloc(sizeof(TreeNode));
    root->val = tmp[*pi];
    ++(*pi);
    // 构建左右子树
    root->left = CreateTree(tmp, pi);
    root->right = CreateTree(tmp, pi);
    // 返回根节点
    return root;
}

// 中序遍历
void InOrder(TreeNode* root)
{
    // 空树
    if (NULL == root)
        return;
    // 左子树
    InOrder(root->left);
    // 打印根节点
    printf("%c ", root->val);
    // 右子树
    InOrder(root->right);
}

int main() {
    
    // 所需变量
    char tmp[101];
    // 输入
    while (scanf("%s", tmp) != EOF)
    {
        // 构建二叉树
        int i = 0;
        TreeNode* root = CreateTree(tmp, &i);
        // 中序遍历
        InOrder(root);
    }

    return 0;
}

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

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

相关文章

MFC中Excel的导入以及使用步骤

参考地址 在需要对EXCEL表进行操作的类中添加以下头文件&#xff1a;若出现大量错误将其放入stdafx.h中 #include "resource.h" // 主符号 #include "CWorkbook.h" //单个工作簿 #include "CRange.h" //区域类&#xff0c;对Excel大…

【C++】类中的“默认成员函数“--构造函数、析构函数、拷贝构造、赋值运算符重载

目录 "默认"成员函数 概念引入&#xff1a; 一、构造函数 问题引入&#xff1a; 1&#xff09;构造函数的概念 2&#xff09;构造函数实例 3&#xff09;构造函数的特性 4)关于默认生成的构造函数 (默认构造函数) 默认构造函数未完成初始化工作实例: 二…

LeetCode【0052】N皇后II

本文目录 1 中文题目2 求解方法&#xff1a;位运算回溯法2.1 方法思路2.2 Python代码2.3 复杂度分析 3 题目总结 1 中文题目 n 皇后问题 研究的是如何将 n 个皇后放置在 n n 的棋盘上&#xff0c;并且使皇后彼此之间不能相互攻击。 给你一个整数 n &#xff0c;返回 n 皇后问…

C语言-详细讲解-P1009 [NOIP1998 普及组] 高精度阶乘之和

目录 1.题目要求 2.题目解读 3.代码实现 4.一些小细节 1.数组储存大整数方式 2.memset函数介绍 3.digit与sum的关系 1.题目要求 2.题目解读 这道题本质就是高精度乘法高精度加法的结合&#xff0c;我之前有出过 高精度算法-保姆级讲解 希望详细了解的小伙伴可以去…

浅谈:基于三维场景的视频融合方法

视频融合技术的出现可以追溯到 1996 年 , Paul Debevec等 提出了与视点相关的纹理混合方法 。 也就是说 &#xff0c; 现实的漫游效果不是从摄像机的角度来看 &#xff0c; 但其仍然存在很多困难 。基于三维场景的视频融合 &#xff0c; 因其直观等特效在视频监控等相关领域有着…

Qt_day10_程序打包(完结)

目录 1. 设置图标 2. Debug和Release版本 3. 动态链接库 4. 打包 5. 联系项目要求 Qt开发的程序最终都是要给用户使用的&#xff0c;用户的电脑上不可能装一个Qt的开发环境导入项目使用。因此项目项目开发完成后需要打包——制作成安装包&#xff0c;用户直接下载并安装即可使用…

路径规划——RRT-Connect算法

路径规划——RRT-Connect算法 算法原理 RRT-Connect算法是在RRT算法的基础上进行的扩展&#xff0c;引入了双树生长&#xff0c;分别以起点和目标点为树的根节点同时扩展随机树从而实现对状态空间的快速搜索。在此算法中以两棵随机树建立连接为路径规划成功的条件。并且&…

【项目开发 | 跨域认证】JSON Web Token(JWT)

未经许可,不得转载。 文章目录 JWT设计背景:跨域认证JWT 原理JWT 结构JWT 使用方式注意JSON Web Token(缩写 JWT)是目前最流行的跨域认证解决方案,本文介绍它的原理、结构及用法。 JWT设计背景:跨域认证 互联网服务的用户认证流程是现代应用中的核心组成部分,通常的流程…

学习笔记——PLCT:milk-v duo(持续更新)

买板子 官方标配有可能是单板&#xff08;如下图&#xff09;无工具包&#xff0c;记得买之前问一下客服。

Kubernetes-ArgoCD篇-01-简介

1、什么是Argo CD Argo CD 是针对 Kubernetes 的声明式 GitOps 持续交付工具。 Argo CD官方文档地址&#xff1a;https://argo-cd.readthedocs.io Argo CD源码地址&#xff1a;https://github.com/argoproj/argo-cd 1.1 关于Argo Argo是一个开源的项目&#xff0c;主要是扩…

【Python】轻松实现机器翻译:Transformers库使用教程

轻松实现机器翻译&#xff1a;Transformers库使用教程 近年来&#xff0c;机器翻译技术飞速发展&#xff0c;从传统的基于规则的翻译到统计机器翻译&#xff0c;再到如今流行的神经网络翻译模型&#xff0c;尤其是基于Transformer架构的模型&#xff0c;翻译效果已经有了质的飞…

父子线程间传值问题以及在子线程或者异步情况下使用RequestContextHolder.getRequestAttributes()的注意事项和解决办法

用到的工具类&#xff1a; Slf4j Configuration Lazy(false) public class SpringContextUtil{public static HttpServletRequest getRequest() {ServletRequestAttributes servletRequestAttributes (ServletRequestAttributes) RequestContextHolder.getRequestAttributes()…

FRTC8563实时时钟芯片的作用

FRTC8563是NYFEA徕飞公司推出的一款实时时钟芯片&#xff0c;采用SOP-8封装形式。这种封装形式具有体积小、引脚间距小、便于集成等特点&#xff0c;使得FRTC8563能够方便地应用于各种电子设备中&#xff0c;如&#xff1a;安防摄像机、监控摄像机、行车记录仪、车载电子等。 F…

怎么样绑定域名到AWS(亚马逊云)服务器

1&#xff0c;拿着你买的域名去亚马逊申请一个证书。申请证书分两种&#xff0c;一种是去亚马逊后台填域名手动申请 &#xff0c;另一种是通过API来申请&#xff0c;类似如下代码&#xff1a; 2、证验证书。有两种方式&#xff1a;一种是通过邮件&#xff0c;另一种去到域名提供…

从0开始深度学习(28)——序列模型

序列模型是指一类特别设计来处理序列数据的神经网络模型。序列数据指的是数据中的每个元素都有先后顺序&#xff0c;比如时间序列数据&#xff08;股票价格、天气变化等&#xff09;、自然语言文本&#xff08;句子中的单词顺序&#xff09;、语音信号等。 1 统计工具 前面介绍…

边缘计算在工业互联网中的应用

&#x1f493; 博客主页&#xff1a;瑕疵的CSDN主页 &#x1f4dd; Gitee主页&#xff1a;瑕疵的gitee主页 ⏩ 文章专栏&#xff1a;《热点资讯》 边缘计算在工业互联网中的应用 边缘计算在工业互联网中的应用 边缘计算在工业互联网中的应用 引言 边缘计算概述 定义与原理 发展…

蓝桥杯——杨辉三角

代码 package day3;public class Demo2 {public static void main(String[] args) {// TODO Auto-generated method stub// for (int i 0; i < 10; i) {// for (int j 0; j < 10; j) {// System.out.print("外&#xff1a;"i"内&#xff1a;&qu…

uniapp中多角色导致tabbar过多的解决方式

由于项目时间较紧张&#xff0c;找了很多却没找到特别合适的方法&#xff0c;最后使用了此方式。 一、自己封装tabbar组件 这里就不介绍怎么封装了&#xff0c;先说一下缺点&#xff1a; 1.跳转会有白屏问题&#xff08;并且搜了好多资料以及查看官网发现没有特别合适的方法…

【JVM】关于JVM的内部原理你到底了解多少(八股文面经知识点)

前言 &#x1f31f;&#x1f31f;本期讲解关于HTTPS的重要的加密原理~~~ &#x1f308;感兴趣的小伙伴看一看小编主页&#xff1a;GGBondlctrl-CSDN博客 &#x1f525; 你的点赞就是小编不断更新的最大动力 &#x1f386;那么废话不…

机器学习 ---模型评估、选择与验证(1)

目录 前言 一、为什么要有训练集与测试集 1、为什么要有训练集与测试集 2、如何划分训练集与测试集 二、欠拟合与过拟合 1、什么是欠拟合与欠拟合的原因 2、什么是过拟合与过拟合的原因 一些解决模型过拟合和欠拟合问题的常见方法&#xff1a; 解决过拟合问题&#…