【二叉树OJ题(二)】前序遍历&&中序遍历&&后序遍历&&另一颗树的子树&&二叉树遍历&&平衡二叉树(下)

简介: 【二叉树OJ题(二)】前序遍历&&中序遍历&&后序遍历&&另一颗树的子树&&二叉树遍历&&平衡二叉树(下)

4、另一颗树的子树

题述:给你两棵二叉树 root 和 subRoot 。检验 root 中是否包含和 subRoot 具有相同结构和节点值的子树。如果存在,返回 true ;否则,返回 false 。二叉树 tree 的一棵子树包括 tree 的某个节点和这个节点的所有后代节点。tree 也可以看做它自身的一棵子树。

image.png示例 1:

输入:root = [3,4,5,1,2], subRoot = [4,1,2]

输出:trueimage.png示例 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


这道题算是 上一篇博客中: 相同的树 的进阶版,如果没有上一题的铺垫,这题会有点难想到。主要思路是判断 二叉树的每一棵子树是否和 subRoot 相等。


由题得,由于 subRoot 一定不为空,所以一旦 root的子树为空,则返回假;

如果 root 的子树 和 subRoot 相等,那么返回真;

否则 递归左右子树,左右子树中任意一边找到了则 子树存在 。

而这里我们判断是否相等就可以直接复用 相同的树 了。


核心思想:每一层函数栈帧中都包括:如果 root 等于空,返回 false;如果调用相同的树为真,返回 true;否则继续递归

//相同的树
bool isSameTree(struct TreeNode* p, struct TreeNode* q) {
  //p为空,q也为空
  if (p == NULL && q == NULL)
    return true;
  //p和q只有1个为空
  if (p == NULL || q == NULL)
    return false;
  //p和q的val不等
  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) {
  //root等于空
  if (root == NULL)
    return false;
  //调用相同的树
  if (isSameTree(root, subRoot))
    return true;
  //继续递归
  return isSubtree(root->left, subRoot) || isSubtree(root->right, subRoot);
}

image.png

5、二叉树遍历

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


输入描述:

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


输出描述:

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

示例 :

输入:abc##de#g##f###

输出:c b e g d f a

注意此题不同于上面的几道接口题,这里是 I/O 类型的题需要我们自己创建树

根据题意中先序遍历的字符串可以得到:image.png前序构建树,再中序输出树

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
struct TreeNode
{
  char val;
  struct TreeNode* left;
  struct TreeNode* right;
};
//前序构建树
struct TreeNode* CreatTree(char* str, int* pi)
{
  if (str[*pi] == '#')
  {
    //空树数组的下标也要++,且为它malloc空间
    (*pi)++;
    return NULL;
  }
  //malloc空间
  struct TreeNode* root = (struct TreeNode*)malloc(sizeof(struct TreeNode));
  //前序递归
  root->val = str[(*pi)++];
  root->left = CreatTree(str, pi);
  root->right = CreatTree(str, pi);
  return root;
}
//中序输出树
void InOrder(struct TreeNode* root)
{
  if (root == NULL)
    return;
  InOrder(root->left);
  printf("%c ", root->val);
  InOrder(root->right);
}
int main()
{
  char str[100];
  scanf("%s", str);
  int i = 0;
  struct TreeNode* root = CreatTree(str, &i);
  InOrder(root);
  return 0;
}

22f2a35d962742e09685aa2c318cbf3e.png

6、平衡二叉树

描述:给定一个二叉树,判断它是否是高度平衡的二叉树。

本题中,一棵高度平衡二叉树定义为:

一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1 。image.png示例1:

输入:root = [3,9,20,null,null,15,7]

输出:true

e712cfd40e624709ae5f9beefa0c5843.png

示例2:

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

输出:false


示例3:

输入:root = []

输出:true


提示:

树中的节点数在范围 [0, 5000] 内

-104 <= Node.val <= 104


思路:

所谓 平衡二叉树就是任意节点的子树的高度差都小于等于1。

基于这个理解,那么我们可以将它分成:每个节点的子树的高度差小于等于1。


那么:

如果节点为空,则是完全二叉树;如果不为空,就求左右两边子树高度;

再判断左右子树的 高度差的绝对值 是否 大于1 ,大于1则一定不是完全二叉树,返回假;

最后分别递归左右子树,判断左右子树是否满足完全二叉树的条件。

求高度可以使用上上篇博客的 计算二叉树的高度 的接口。

//求二叉树的高度 
int TreeHeight(struct TreeNode* root)
{
    if (root == NULL)
    {
        return 0;
    }
    int leftHeight = TreeHeight(root->left);
    int rightHeight = TreeHeight(root->right);
    return leftHeight > rightHeight ? leftHeight + 1 : rightHeight + 1;
}
bool isBalanced(struct TreeNode* root)
{
    // 根节点为空,是完全二叉树
    if (root == NULL)
    {
        return true;
    }
    // 求左右两边高度
    int leftHeight = TreeHeight(root->left);
    int rightHeight = TreeHeight(root->right);
    // 绝对值大于1一定不是完全二叉树
    if (abs(leftHeight - rightHeight) > 1)
    {
        return false;
    }
    return isBalanced(root->left) && isBalanced(root->right);
}

496a55b040a540e9aa429fbdbcfeeb4c.png

总结:

今天我们完成了二叉树OJ题(二),通过分析明白了思路和原理,愿这篇博客能帮助大家理解这些OJ题,到这里,我们的二叉树就暂告一段落啦。接下来将更新排序算法的相关知识点。希望我的文章和讲解能对大家的学习提供一些帮助。

当然,本文仍有许多不足之处,欢迎各位小伙伴们随时私信交流、批评指正!我们下期见~

c3ad96b16d2e46119dd2b9357f295e3f.jpg

目录
打赏
0
0
0
0
0
分享
相关文章
网页自动提交Form表单的方法
在数字化时代,自动化任务如网页自动提交Form表单,能大幅提升效率。这涉及自动填写注册信息等场景。本文概述了多种实现方式:JavaScript可直接在前端自动填充并提交;Python结合Selenium模拟真实用户操作;AOKSend作为API工具发送表单数据;第三方工具如iMacros、AutoHotkey和Zapier提供非编程自动化选项。根据需求选择合适方法,可显著提升工作效能,减少重复性劳动。
日志管理:收集和分析Docker容器日志
容器化技术的普及使得应用的部署和管理更加便捷,但随之而来的挑战之一是有效地管理和分析容器产生的大量日志。本文将深入探讨Docker容器日志管理的重要性,介绍常用的日志收集工具,以及如何分析和利用这些日志数据,提供更为丰富和实际的示例代码,帮助大家更好地理解和应用日志管理的关键技术。
动态规划dp(三个案例详解)
动态规划dp(三个案例详解)
259 0
C语言数据结构(11)--数组描述子节点的树
本文目录 1. 啥是树 2. 树的相关概念 3. 如何用数据结构对树进行描述 4. 代码实现
180 0
C语言数据结构(11)--数组描述子节点的树
还记得吗?那个曾让你头疼的Waiting For Debugger
Waiting For Debugger,开发者,你还熟悉吗?到这里卡死了。 Waiting For Debugger1.jpg 今天公司内部人员给我反馈一个问题,说我们的测试包不能用,不知道为什么。
1833 0
第三方工具 - 关于echarts下钻功能的一些总结.js
废话:好久没有写博客了,每每看着自己的'战绩'都有点愧疚,但是这段时间确实学习了不少东西,待我慢慢地一 一梳理,将之消化并分享。 ---------------------------$O_O$--------------------------- echarts下钻:就是点击echarts图表,让图表展开更详细的下一级数据。
2758 0
objective-C中如何判断一个类中有没有定义某个方法
C#中可以通过反射分析元数据来解决这个问题,示例代码如下: using System; using System.Reflection; namespace Hello { class Program { static void Main(s...
786 0
首个云超算国标正式发布!
近日,我国首个云超算国家标准GB/T 45400-2025正式发布,将于今年10月实施。该标准由阿里云联合多家机构起草,为云超算在高性能计算领域的应用提供规范。云超算结合传统HPC与云计算优势,解决传统HPC复杂、昂贵等问题。阿里云E-HPC V2.0是国内首批通过该标准认证的产品,支持大规模弹性计算,显著降低成本。新标准将推动算力基础设施迈向标准化、智能化新时代。
快速部署实现Bolt.diy
Bolt.diy 是 Bolt.new 的开源版本,提供灵活的自然语言交互与全栈开发支持。基于阿里云函数计算 FC 和百炼模型服务,最快5分钟完成部署。新手注册阿里云账号后可领取免费额度,按指引开通相关服务并授权。通过项目模板一键部署,配置 API-KEY 后即可使用。Bolt.diy 支持多种场景,如物联网原型开发、久坐提醒、语音控制灯光等,助力快速实现创意应用。
2242 17

热门文章

最新文章

AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等