二叉树经典OJ练习

个人主页:C++忠实粉丝
欢迎 点赞👍 收藏✨ 留言✉ 加关注💓本文由 C++忠实粉丝 原创

二叉树经典OJ练习

收录于专栏【数据结构初阶】
本专栏旨在分享学习数据结构学习的一点学习笔记,欢迎大家在评论区交流讨论💌

目录

前置说明 

1. 单值二叉树

2. 相同的树

3. 对称二叉树

4. 二叉树的前序遍历

5. 二叉树中序遍历

6. 二叉树的后序遍历

7. 另一颗树的子树


前置说明 

这里大家需要有二叉树的一些基础,还不是很了解的宝子们可以点击下方链接进行查看

---数据结构之二叉树的超详细讲解(3)--(二叉树的遍历和操作)-CSDN博客

1. 单值二叉树

Oj链接--965. 单值二叉树 - 力扣(LeetCode)

题目描述:

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

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

示例 1:

输入:[1,1,1,1,1,null,1]
输出:true

示例 2:

输入:[2,2,2,5,2]
输出:false

提示:

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

分析:

题目中给定树的节点数范围是 [1, 100],这里我们就不需要额外判断空节点的情况,我们只需要对二叉树进行遍历一遍,如果遇到空节点返回true,如果root左节点或右节点val不等于root->val,返回false,将最后的结果上传,即可得到最终的结果.

代码展示: 

bool isUnivalTree(struct TreeNode* root) {if(root == NULL)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);
}

核心逻辑

  1. 空树检查

    if(root == NULL) return true;

    这里首先检查根节点是否为空。如果根节点为空,则该树被认为是单值二叉树,返回 true

  2. 左子节点值检查

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

    接下来检查左子节点。如果左子节点存在且其值与根节点的值不相同,则该树不是单值二叉树,返回 false

  3. 右子节点值检查

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

    同样地,检查右子节点。如果右子节点存在且其值与根节点的值不相同,则该树不是单值二叉树,返回 false

  4. 递归检查子树

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

    如果当前节点及其直接子节点都满足条件,则递归检查左子树和右子树。只有在左右子树都是单值二叉树的情况下,当前树才是单值二叉树。

总结

该函数通过递归检查每个节点及其子节点的值是否与根节点的值相同来判断整个二叉树是否是单值二叉树。如果某个节点的值与其父节点不同,立即返回 false。否则,继续递归检查其子树,最终返回整个树的结果。

2. 相同的树

OJ链接--100. 相同的树 - 力扣(LeetCode)

题目描述:

给你两棵二叉树的根节点 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

提示:

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

分析:

两棵树上的节点数目都在范围 [0, 100] 内,说明这里需要进行空树的判断,我们需要先进行判断,当两棵树节点都为空时,满足条件,返回true.当两个节点只有一个为空时,不满足条件,返回false.当两个节点都不为空时,比较两个节点的val,不相等返回false.然后递归遍历两棵树.

代码展示:

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);
}
  1. 首先检查 p 和 q 是否同时为 NULL,如果是,说明两棵树都为空,返回 true
  2. 然后检查 p 和 q 是否其中一个为 NULL,另一个不是。如果是,说明两棵树中的节点个数不同,返回 false
  3. 接着检查 p 和 q 的当前节点值是否相同,如果不同,返回 false
  4. 最后,通过递归调用 isSameTree 函数比较两棵树的左子树和右子树是否相同,如果均相同则返回 true,否则返回 false

这段代码非常简洁而且有效地比较了两棵树是否相同。它利用了递归的特性,逐层比较树的节点值以及对应的子树,从而判断两棵树是否相同。

3. 对称二叉树

OJ链接--101. 对称二叉树 - 力扣(LeetCode)

题目描述:

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

示例 1:

输入:root = [1,2,2,3,4,4,3]
输出:true

示例 2:

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

提示:

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

代码展示:

bool check(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 check(p->left, q->right) && check(p->right, q->left);elsereturn false;
}bool isSymmetric(struct TreeNode* root) {return check(root, root);
}

分析: 

  • check 函数:

    • 首先检查 p 和 q 是否同时为 NULL,如果是,说明两个节点都为空,返回 true
    • 然后检查 p 和 q 是否其中一个为 NULL,另一个不是。如果是,说明两个节点中的一个为空,另一个不为空,返回 false
    • 接着检查 p 和 q 的值是否相等,如果相等,则递归地比较 p 的左子树和 q 的右子树,以及 p 的右子树和 q 的左子树是否对称。如果均对称,则返回 true,否则返回 false
  • isSymmetric 函数:

    • 调用 check 函数,并传入根节点的左右子树作为参数进行比较。

这段代码利用递归的方式判断了一棵二叉树是否对称。它通过比较树的左右子树是否镜像对称来判断整棵树是否对称。整体上,这段代码实现了一个简洁而有效的对称性判断算法。

函数递归展开图:

4. 二叉树的前序遍历

OJ链接--144. 二叉树的前序遍历 - 力扣(LeetCode)

题目描述:

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

示例 1:

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

示例 2:

输入:root = []
输出:[]

示例 3:

输入:root = [1]
输出:[1]

示例 4:

输入:root = [1,2]
输出:[1,2]

示例 5:

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

提示:

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

分析:

注意这道题目的要求:

/**

 * Definition for a binary tree node.

 * struct TreeNode {

 *     int val;

 *     struct TreeNode *left;

 *     struct TreeNode *right;

 * };

 */

/**

 * Note: The returned array must be malloced, assume caller calls free().

 */

int* preorderTraversal(struct TreeNode* root, int* returnSize) {}

这里我们需要返回的是前序遍历好的数组,而且需要我们自己malloc创建.函数的参数一个是根节点一个是节点个数,要我们实现的是一个输出型函数.

代码展示: 

int TreeSize(struct TreeNode* root)
{return root == NULL ? 0 : TreeSize(root->left) + TreeSize(root->right) + 1;
}void preOrder(struct TreeNode* root, int* a, int* pi)
{if(root == NULL)return;a[(*pi)++] = root->val;preOrder(root->left, a, pi);preOrder(root->right, a, pi);
}int* preorderTraversal(struct TreeNode* root, int* returnSize) {*returnSize = TreeSize(root);int* a = (int*)malloc(sizeof(int)*(*returnSize));int i = 0;preOrder(root, a, &i);return a;
}

这段代码是关于二叉树前序遍历的实现,其中包括了计算二叉树节点总数和返回前序遍历结果的功能。让我们对这段代码进行详细分析:

int TreeSize(struct TreeNode* root) { return root == NULL ? 0 : TreeSize(root->left) + TreeSize(root->right) + 1; }

这部分代码是计算二叉树节点总数的函数 TreeSize,使用了递归的方式来统计节点数量。在每个节点上,它会递归地调用自身来计算左子树和右子树的节点数,并加上当前节点。

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

这部分代码是实现前序遍历的函数 preOrder,它将遍历得到的节点值存储在数组 a 中,使用指针 pi 来跟踪数组的索引位置。

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

最后,preorderTraversal 函数整合了前两部分的功能。它先计算二叉树的节点总数,然后动态分配一个数组 a 来存储前序遍历的结果,并调用 preOrder 函数来填充数组。最终将数组返回。

总结

这段代码实现了计算二叉树节点总数并返回其前序遍历结果的功能。通过递归的方式遍历二叉树,将节点值按前序遍历顺序存储在数组中,并返回该数组。这样的实现使得我们能够方便地获取二叉树的前序遍历结果,并且能够有效地处理动态分配内存以存储结果。

5. 二叉树中序遍历

OJ链接--94. 二叉树的中序遍历 - 力扣(LeetCode)

题目描述:

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

示例 1:

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

示例 2:

输入:root = []
输出:[]

示例 3:

输入:root = [1]
输出:[1]

提示:

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

后面的中序和后序跟前序相差不大,这里就不过多解释. 

代码展示:

int TreeSize(struct TreeNode* root)
{return root == NULL ? 0 : TreeSize(root->left) + TreeSize(root->right) + 1;
}void inOrder(struct TreeNode* root, int* a, int* pi)
{if(root == NULL){return;}inOrder(root->left,a,pi);a[(*pi)++] = root->val;inOrder(root->right,a,pi);
}int* inorderTraversal(struct TreeNode* root, int* returnSize) {*returnSize = TreeSize(root);int* a = (int*)malloc(sizeof(int)*(*returnSize));int i = 0;inOrder(root,a,&i);return a;
}

6. 二叉树的后序遍历

OJ链接--145. 二叉树的后序遍历 - 力扣(LeetCode)

题目描述:

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

示例 1:

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

示例 2:

输入:root = []
输出:[]

示例 3:

输入:root = [1]
输出:[1]

提示:

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

代码展示:

int TreeSize(struct TreeNode* root)
{return root == NULL ? 0 : TreeSize(root->left) + TreeSize(root->right) + 1;
}void postOrder(struct TreeNode* root, int* a, int* pi)
{if(root == NULL)return;postOrder(root->left, a, pi);postOrder(root->right, a, pi);a[(*pi)++] = root->val;
}int* postorderTraversal(struct TreeNode* root, int* returnSize) {*returnSize = TreeSize(root);int* a = (int*)malloc(sizeof(int)*(*returnSize));int i = 0;postOrder(root, a, &i);return a;
}

7. 另一颗树的子树

OJ链接--572. 另一棵树的子树 - 力扣(LeetCode)

题目描述:

给你两棵二叉树 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

提示:

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

分析:

遍历root树,找到root的所有子树与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 && isSameTree(root, subRoot))return true;return isSubtree(root->left,subRoot) || isSubtree(root->right, subRoot);
}

注意:这里需要用到我们之前已经解决的相同的树的问题

该函数用来判断二叉树 subRoot 是否是二叉树 root 的子树。

逻辑解释

  1. 空树检查

    if(root == NULL) return false;

    如果 root 是空树,直接返回 false,因为空树不可能包含任何非空子树。

  2. 根节点值比较及完整树比较

    if(root->val == subRoot->val && isSameTree(root, subRoot)) return true;

    如果 root 的当前节点值与 subRoot 的根节点值相同,并且 root 从当前节点开始的子树与 subRoot 完全相同(通过调用 isSameTree 函数进行判断),则返回 true

  3. 递归检查左右子树

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

    如果上述条件都不满足,则递归地检查 root 的左子树和右子树,看其中是否存在与 subRoot 相同的子树。如果任意一个子树包含 subRoot,返回 true

总结

这两个函数结合起来可以有效地判断一棵二叉树是否是另一棵二叉树的子树。具体步骤如下:

  1. 使用 isSubtree 函数遍历 root 的每个节点。
  2. 对于每个节点,检查该节点开始的子树是否与 subRoot 完全相同。
  3. 如果找到一个与 subRoot 相同的子树,立即返回 true
  4. 如果没有找到,继续遍历 root 的左右子树,直到所有节点都检查完毕。

这种方法通过递归遍历和子树比较,确保准确判断子树关系。

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

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

相关文章

八、(正点原子)Linux内核定时器实验

定时器是我们最常用到的功能&#xff0c;一般用来完成定时功能&#xff0c;本章我们就来学习一下 Linux 内核提供的定时器 API 函数&#xff0c;通过这些定时器 API 函数我们可以完成很多要求定时的应用。 Linux内核也提供了短延时函数&#xff0c;比如微秒、纳秒、毫秒延时函数…

【Linux基础】SSH登录

SSH简介 安全外壳协议&#xff08;Secure Shell Protocol&#xff0c;简称SSH&#xff09;是一种加密的网络传输协议&#xff0c;可在不安全的网络中为网络服务提供安全的传输环境。 SSH通过在网络中建立安全隧道来实现SSH客户端与服务器之间的连接。 SSH最常见的用途是远程登…

LeetCode 算法:二叉树的最大深度 c++

原题链接&#x1f517;&#xff1a;二叉树的最大深度 难度&#xff1a;简单⭐️ 题目 给定一个二叉树 root &#xff0c;返回其最大深度。 二叉树的 最大深度 是指从根节点到最远叶子节点的最长路径上的节点数。 示例 1&#xff1a; 输入&#xff1a;root [3,9,20,null,…

【高考选专业 | 家长篇】2024,计算机何去何从?小P老师带你看

目录 2024年&#xff0c;计算机相关专业还值得选择吗&#xff1f;1.行业竞争现状2.专业前景分析 2024年&#xff0c;计算机相关专业还值得选择吗&#xff1f; 随着2024年高考落幕&#xff0c;数百万高三学生又将面临人生中的重要抉择&#xff1a;选择大学专业。有人欢喜&#x…

操作系统真象还原:用户进程

第11章-用户进程 这是一个网站有所有小节的代码实现&#xff0c;同时也包含了Bochs等文件 11.1 为什么要有任务状态TSS Linux 任务切换未采用 Intel 的做法&#xff0c;而是用了一套自己的方法&#xff0c;只是用了 TSS 的一小部分功能。 操作系统最直接控制的就是 CPU&…

ubuntu22.04笔记: 更换为阿里源

没有按照LTS 版本 会遇到下面问题&#xff1a; 参考&#xff1a;https://zhuanlan.zhihu.com/p/691625646 Ubuntu 22.04代号为&#xff1a;jammy Ubuntu 20.04代号为&#xff1a;focal Ubuntu 19.04代号为&#xff1a;disco Ubuntu 18.04代号为&#xff1a;bionic Ubuntu …

对于C++ 程序员来说,35岁魔咒是否存在?

大家常说程序员职业生涯会在35岁左右遇到所谓的“35岁魔咒”。这意味着在这个年龄段&#xff0c;程序员可能会面临就业不稳定或职业发展的挑战。对于C程序员来说&#xff0c;这个问题更加引人关注。 随着时间的推移&#xff0c;技术行业不断演进&#xff0c;新的编程语言层出不…

vue上传文件拿到File,下载文件到本地

vue中使用upload组件上传pdf文件&#xff0c;拿到File内容后&#xff0c;下载pdf文件到本地vue中根据url下载pdf文件到本地 File文件内容的格式 注意&#xff1a;如果使用iview的upload组件上&#xff0c;要获取File文件&#xff0c;需要在before-upload钩子上获取 async down…

Ubuntu iso 镜像下载 步骤截图说明

Ubuntu镜像下载&#xff0c;在这个网址&#xff1a; Enterprise Open Source and Linux | Ubuntu 步骤如下图所示&#xff1a; 1、登入网址 2、点击Get Ubuntu 3、点击Download Ubuntu Desktop 后续点击Downloadload 24.04 LTS直接下载就行 如果需要下载其它版本&#xf…

STM32学习之一:什么是STM32

目录 1.什么是STM32 2.STM32命名规则 3.STM32外设资源 4. STM32的系统架构 5. 从0到1搭建一个STM32工程 学习stm32已经很久了&#xff0c;因为种种原因&#xff0c;也有很久一段时间没接触过stm32了。等我捡起来的时候&#xff0c;发现很多都已经忘记了&#xff0c;重新捡…

【驱动篇】龙芯LS2K0300之按键驱动

实验过程 实验目的&#xff1a; 在龙芯开发板上面验证GPIO按键的输入过程 ① 根据原理图连接按键板 ② 将4个i2c引脚的功能复用为GPIO ③ 注册input设备驱动&#xff0c;绑定中断处理函数&#xff0c;使用定时器消抖 原理图 4个按键引脚&#xff1a;CPU_I2C0_SCL -> G…

艺体培训机构管理系统的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;管理员管理&#xff0c;教师管理&#xff0c;学员管理&#xff0c;活动管理&#xff0c;课程管理&#xff0c;选课信息管理 前台账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;论…

【会议征稿,ACM出版】2024年图像处理、智能控制与计算机工程国际学术会议(IPICE 2024,8月9-11)

2024年图像处理、智能控制与计算机工程国际学术会议&#xff08;IPICE 2024&#xff09;将于2024年8月9-11日在中国福州举行。本届会议由阳光学院、福建省空间信息感知与智能处理重点实验室、空间数据挖掘与应用福建省高校工程研究中心联合主办。 会议主要围绕图像处理、智能控…

分布式定时任务系列10:XXL-job源码分析之路由策略

传送门 分布式定时任务系列1&#xff1a;XXL-job安装 分布式定时任务系列2&#xff1a;XXL-job使用 分布式定时任务系列3&#xff1a;任务执行引擎设计 分布式定时任务系列4&#xff1a;任务执行引擎设计续 分布式定时任务系列5&#xff1a;XXL-job中blockingQueue的应用 …

Go语言的诞生背景

人不走空 &#x1f308;个人主页&#xff1a;人不走空 &#x1f496;系列专栏&#xff1a;算法专题 ⏰诗词歌赋&#xff1a;斯是陋室&#xff0c;惟吾德馨 目录 &#x1f308;个人主页&#xff1a;人不走空 &#x1f496;系列专栏&#xff1a;算法专题 ⏰诗词歌…

Linux操作系统处理器调度基本准则和实现

1&#xff0c;基本概念 在多道程序系统中&#xff0c;进程的数量往往多于处理机的个数&#xff0c;进程争用处理机的情况就在所难免。处理机调度是对处理机进行分配&#xff0c;就是从就绪队列中&#xff0c;按照一定的算法&#xff08;公平、低效&#xff09;选择一个进程并将…

mysql学习——SQL中的DDL和DML

SQL中的DDL和DML DDL数据库操作&#xff1a;表操作 DML添加数据修改数据删除数据 学习黑马MySQL课程&#xff0c;记录笔记&#xff0c;用于复习。 DDL DDL&#xff1a;Data Definition Language&#xff0c;数据定义语言&#xff0c;用来定义数据库对象(数据库&#xff0c;表&…

C语言入门课程学习笔记8:变量的作用域递归函数宏定义交换变量

C语言入门课程学习笔记8 第36课 - 变量的作用域与生命期&#xff08;上&#xff09;第37课 - 变量的作用域与生命期&#xff08;下&#xff09;实验—局部变量的作用域实验-变量的生命期 第38课 - 函数专题练习第39课 - 递归函数简介实验小结 第40课 - C 语言中的宏定义实验小结…

基于Java的学生成绩管理系统

你好呀&#xff0c;我是计算机学姐码农小野&#xff01;如果有相关需求&#xff0c;可以私信联系我。 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;Java技术&#xff0c;B/S结构 工具&#xff1a;MyEclipse&#xff0c;MySQL 系统展示 首页 个人中…

基于YOLOv5+pyqt5的跌倒检测系统(含pyqt页面、训练好的模型)

简介 跌倒是老年人和身体不便者常见的意外事故&#xff0c;及时检测和处理跌倒事件对于保障他们的安全至关重要。为了提高对跌倒事件的监控效率&#xff0c;我们开发了一种基于YOLOv5目标检测模型的跌倒检测系统。本报告将详细介绍该系统的实际应用与实现&#xff0c;包括系统…