C语言数据结构-二叉树基础练习

繁霜尽是心头血

洒向千峰秋叶丹


目录

二叉树最大的深度 

思路

代码展示

 单值二叉树

思路

代码展示

相同的树 

思路

代码展示

 对称二叉树

思路

代码展示

另一颗树的子树 

思路

代码展示

 

二叉树最大的深度 

 题目链接:二叉树最大的深度


给定一个二叉树 root ,返回其最大深度。

二叉树的 最大深度 是指从根节点到最远叶子节点的最长路径上的节点数。

示例 1:

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

示例 2:

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

提示:

  • 树中节点的数量在 [0, 10^4] 区间内。
  • -100 <= Node.val <= 100

思路

例如 如果我们知道了左子树和右子树的最大深度r

那么该二叉树的最大深度即 max⁡(l,r) + 1左右子树的最大深度加根节点

我们可以把它看做是后序遍历左右根),函数递归完再用其返回值做树的高度计算

步骤

<1>确定终止条件:如果为空节点的话,就返回0,表示高度为0

 if(root == NULL)
    return 0;

<2>找出重复的子问题:递归左子树的最大高度,递归右子树的最大高度

    int left = maxDepth(root->left);
    int right =  maxDepth(root->right);

<3>根据题目进行整改:求出左右子树的最大高度再进行比较,取最大高度在加一

return (left>right?left:right)+1;

代码展示

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

时间复杂度为 O(n) :在递归过程中每个节点都被遍历到

空间复杂度为 O(n) :此外在递归过程中调用了额外的栈空间,栈的大小取决于二叉树的高度,设二叉树最坏情况下的高度为 n


注意:

 public int maxDepth(TreeNode root) {
    if(root == null)
        return 0;
        return 1 + (maxDepth(root.left) > maxDepth(root.right)? maxDepth(root.left):maxDepth(root.right));
}

这样写逻辑上是对的,但是会超时,因为多算了几遍 maxDepth( ) ,多递归了,应该用变量存储一下 maxDepth( ) 的值

 单值二叉树

题目链接:单值二叉树


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

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

示例 1:

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

示例 2:

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

提示:

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

思路

因为单值二叉树每个节点都具有相同的值,那么我们只要比较左右子树节点的值是否与根节点相同。如果我们从正面来判断一个树是否为单值二叉树很难,所以我们可以考虑反面。例如 左子树为空或者节点的值不等于根节点的值即返回 false 我们每次判断都返回反面结果,最后不满足条件的必然是 true

步骤

<1>确定终止条件:如果节点为空,说明比较到了尽头,返回 true

if(root == NULL)
    return true;

<2>判断单值二叉树的条件:判断树的左右子树是否为空以及节点的值是否等于根的值

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

<3>找出重复的子问题:递归左右子树判断是否满足相等的条件

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

代码展示

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);    
}

时间复杂度O(n):其中 n 是二叉树的节点个数。我们遍历二叉树的每个节点至多一次。

空间复杂度O(n):即为深度优先搜索中需要使用的栈空间。

相同的树 

题目链接:相同的树


给你两棵二叉树的根节点 p 和 q ,编写一个函数来检验这两棵树是否相同。

如果两个树在结构上相同,并且节点具有相同的值,则认为它们是相同的。

示例 1:

输入:p = [1,2,3], q = [1,2,3]
输出:true

示例 2:

输入:p = [1,2,1], q = [1,1,2]
输出:false

提示:

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

思路

判断两棵二叉树是否相同,可以通过递归对二叉树各个节点进行比较,以判断两棵树是否相同。

步骤

<1>确定终止条件

如果两个节点都为空,说明比较到了尽头,返回 true
如果一个节点为空,另一个节点不为空,两节点不同,返回 false
if(p == NULL && q == NULL)
        return true;
if(p == NULL || q == NULL)
        return false;

<2>判断相同二叉树的条件:如果 p 和 q 都不为空,判断根结点值是否相同,相同则继续判断两颗树的左右子树值都相同,返回 true,否则返回 false

if(p->val != q->val)
    return false;

<3>找出重复的子问题:递归判断两颗树的左右子树判断是否相同

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

代码展示

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);
}

 对称二叉树

题目链接:对称二叉树


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

思路

对称二叉树如图所示,要判断一个二叉树是否为对称二叉树,实际上就是要判断根节点的左右两个子树是否镜像对称

那么两个树在什么情况下互为镜像?

两个树的根结点具有相同的值
每个树的右子树都与另一个树的左子树镜像对称
 

我们可以借助上一题的思路,我们把这个树的左右子树拆解成两个树进行判断

例如 我们用 root1 代表左子树的根,root2 代表右子树的根,然后递归先判断树的节点是否对称再判断 root1 的左子树和 root2 的右子树 是否相同

<1>确定终止条件

(1)如果两个节点都为空,说明比较到了尽头,返回 true

(2)如果一个节点为空,另一个节点不为空,则树不对称,返回 false

 if(root1 == NULL && root2 ==NULL)
        return true;
 if(root1 == NULL || root2 == NULL)
        return false;

<2>判断对称二叉树的条件:判断 root1 的左子树和 root2 的右子树 是否相同

 if(root1->val != root2->val)
        return false;

<3>找出重复的子问题:递归判断两颗树的左右子树的镜像是否对称以及值是否相等

 return _isSymmetric(root1->left,root2->right)&&_isSymmetric(root1->right,root2->left);

代码展示

bool _isSymmetric(struct TreeNode* root1,struct TreeNode* root2) 
{
    if(root1 == NULL && root2 ==NULL)
        return true;
    if(root1 == NULL || root2 == NULL)
        return false;
    if(root1->val != root2->val)
        return false;
        return _isSymmetric(root1->left,root2->right)&&_isSymmetric(root1->right,root2->left);
}

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

假设树上一共 n 个节点。

时间复杂度:这里遍历了这棵树,渐进时间复杂度为 O(n)。
空间复杂度:这里的空间复杂度和递归使用的栈空间有关,这里递归层数不超过 n,故渐进空间复杂度为 O(n)。

另一颗树的子树 

 题目链接:另一颗树的子树


给你两棵二叉树 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]
  • -10^4 <= root.val <= 10^4
  • -10^4 <= subRoot.val <= 10^4

思路

如何判断一个树是另一个树的子树呢?就和我们找子数组一样(找相同)

<1>我们可以定义两个指针(指针p 指向root的比较节点,指针q 指向subRoot的根)

<2>先从 root 的左树开始,位置于root当前节点的指针p 与 在subRoot根节点的指针q 共同遍历进行比较,若节点与节点值相同则代表 subRoot 为子树,否则再递归右树,仍然没有则不是子树

找相同的代码我们可以借助之前(相同的树的代码)

判断subRoot是否是root的子树

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>确定终止条件:树的节点为空说明树不存在或者递归到了尽头,直接返回 false

if (root == NULL)
    return false;

<2>判断子树的条件:判断 root 的枝干和 subRoot 的是否相同,相同返回 true

 bool rootBool = isSameTree(root,subRoot);

<3>找出重复的子问题:递归root的左右子树判断是否有枝干与subRoot一致

return rootBool || isSubtree(root->left, subRoot) || isSubtree(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;
    bool rootBool = isSameTree(root,subRoot);
        return rootBool || isSubtree(root->left, subRoot) || isSubtree(root->right, subRoot);
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

osgEarth学习笔记3-第二个Osg QT程序

原文链接 打开QT Creator&#xff0c;新建一个窗口项目。 QT版本如下&#xff1a; 修改pro文件 QT core gui greaterThan(QT_MAJOR_VERSION, 4): QT widgets CONFIG c11 DEFINES QT_DEPRECATED_WARNINGS SOURCES \main.cpp \mainwindow.cpp HEADERS \mainwindow…

释放创造力,Nik Collection 6 by DxO 点亮你的视觉世界

在数字摄影时代&#xff0c;后期处理是提升摄影作品品质的重要环节。而Nik Collection 6 by DxO作为一套优秀的滤镜插件套装&#xff0c;不仅为摄影师提供了丰富的后期处理工具&#xff0c;更让他们能够释放无限的创造力&#xff0c;打造出惊艳的视觉作品。 Nik Collection 6 …

Unity定时播放音乐

一、需求 需要定时在早上8:50&#xff0c;中午12:00&#xff0c;下午13:10定时播放音乐 二、实现步骤 依次在unity创建背景图、主文字提示、时间文字提示、音量控制器及音量文字提示、退出按钮、播放按钮&#xff0c;暂停按钮 在Canvas下创建一个Script脚本&#xff1a;获取…

路由器里如何设置端口映射?

在互联网时代&#xff0c;我们经常需要将内部网络的服务暴露到公网以便其他人访问。直接将内部网络暴露在公网上存在一定的安全风险。为了解决这个问题&#xff0c;我们可以利用路由器里设置端口映射来实现将特定端口的访问请求转发到内部网络的特定设备上。 端口映射的原理 端…

SolidWorks教育版:为何它成为工程教育的优选?

你是否曾经想过&#xff0c;为什么SolidWorks教育版在工程教育中如此受欢迎&#xff1f;作为专业的数码科技博主&#xff0c;今天就来给大家揭秘。首先&#xff0c;我们要明白SolidWorks是一款功能强大的三维CAD软件&#xff0c;广泛应用于机械、汽车、航空等领域。而教育版则是…

从零开始搭建游戏服务器 第四节 MongoDB引入并实现注册登录

这里写目录标题 前言正文添加依赖安装MongoDB添加MongoDB相关配置创建MongoContext类尝试初始化DB连接实现注册功能测试注册功能实现登录逻辑测试登录流程 结语下节预告 前言 游戏服务器中, 很重要的一点就是如何保存玩家的游戏数据. 当一个服务端架构趋于稳定且功能全面, 开发…

Redis部署方式(三)主从模式

在前面单机版的基础上&#xff0c;41为主&#xff0c;30为从。 一、主从搭建 1、主Redis安装 41机器redis主要配置 requirepass redis#!_41 bind 0.0.0.0 port 6379 daemonize yes 2、从redis安装 30机器redis主要配置 requirepass redis#!_30 bind 0.0.0.0 port 6380 da…

【SpringBoot3.x教程04】SpringBoot如何自定义starter

前言&#xff1a;什么是Starter POMs Starter POMs是预配置的依赖集合&#xff0c;旨在提供一种快速的方式来引入和管理Spring及相关技术栈的依赖。每个Starter POM都是针对特定的Spring模块或技术场景设计的。使用Starter POM&#xff0c;开发者只需要添加一个依赖项&#xff…

67、自定义通信帧协议解析

帧格式&#xff1a;方便自定义长度多种帧标识传输 格式规定 帧标识A 类型 备注 A<0x0F 短帧 数据长度1字节 A>0x0F 长帧 数据长度2字节 短帧:帧标识 帧标识取反 帧用户数据字节数 用户数据…用户数据 长帧:帧标识 帧标识取反 帧用户数据字节数(高8位) 帧用户数据字节数…

卸载应用无残留,App Cleaner Uninstaller Pro助你轻松管理Mac

App Cleaner & Uninstaller Pro是一款专为Mac用户设计的强大应用程序清理和卸载工具。这款软件拥有出色的卸载功能&#xff0c;能够彻底删除不再需要的应用程序及其相关文件和数据&#xff0c;确保Mac磁盘空间得到高效释放。同时&#xff0c;其强大的搜索功能可以快速找到与…

机器视觉系统选型-镜头参数

镜头参数&#xff1a; 光圈&#xff1a;光圈是一个用来控制镜头通光量的装置 &#xff0c;表示光圈大小我们是用光圈值&#xff08;F值&#xff09; &#xff0c;如F1.4&#xff0c;F2&#xff0c;F2.8 焦距&#xff08;Focus&#xff09;&#xff1a;透镜中心到其焦点的距离 景…

蓝桥杯刷题(十二)

1.答疑 代码 n int(input()) L [] for i in range(n):a,b,c map(int,input().split())A ab # 进入和答疑时间B abc # 个人总用时L.append([A,B]) L.sort(keylambda x:x[1]) # 个人总用时短的优先 ans tmp 0 # ans为发消息时刻&#xff0c;tmp为前一个人的总用时 for i …

C++ —— 类和对象(终)

目录 1. 日期类的实现 1.1 前置 和 后置 重载 1.2 >> 和 << 的重载 2. const 成员 3. 取地址及const取地址操作符重载 4. 再谈构造函数 4.1 构造函数体赋值 4.2 初始化列表 4.3 隐式类型转换 4.4 explict 关键字 5. static 成员 5.1 概念 5.2 特性 …

最新梨花带雨网页音乐播放器二开优化修复美化版全开源版本源码下载

最新梨花带雨网页音乐播放器二开优化修复美化版全开源版本源码下载 梨花带雨播放器基于thinkphp6开发的XPlayerHTML5网页播放器前台控制面板,支持多音乐平台音乐解析。二开内容:修复播放器接口问题,把接口本地化,但是集成外链播放器接口就不本地化了,我花钱找人写的理解下…

iOS图片占内存大小与什么有关?

1. 问&#xff1a;一张图片所占内存大小跟什么有关&#xff1f; 图片所占内存大小&#xff0c;与图片的宽高有关 我们平时看到的png、jpg、webp这些图片格式&#xff0c;其实都是图片压缩格式。通过对应的算法来优化了大小以节省网络传输与本地保存所需的资源。 但是当我们加…

vant4中如何修改Dialog弹框内容的字体大小

最近在开发一个移动端的需求&#xff0c;用的UI组件库是vant4 简单地总结一下&#xff0c;如何修改Dialog弹框内容的字体大小 我们先看一下Dialog弹框简单的使用 import { showConfirmDialog } from vant;showConfirmDialog({title: 标题,message:如果解决方法是丑陋的&#…

抖音视频无水印下载软件|视频批量提取工具

视频无水印下载软件 随着视频平台上涌现出越来越多精彩的视频内容&#xff0c;很多用户希望能够下载自己喜爱的视频进行保存或分享。为了满足用户需求&#xff0c;我们推出了专业的视频无水印下载软件&#xff0c;让您可以轻松快捷地获取喜欢的视频内容。以下是该软件的安装教…

Sealos 云开发:Laf 出嫁了,与 Sealos 正式结合!

千呼万唤始出来&#xff0c;Laf 云开发最近已正式与 Sealos 融合&#xff0c;入住 Sealos&#xff01;大家可以登录 Sealos 公有云 体验和使用&#xff0c;现在正式介绍一下 Sealos 云开发。 Sealos 云开发是什么&#xff1f; 如图&#xff0c;我们把 Laf 融合到 Sealos 中去了…

MySQL如何用phpMyAdmin创建定时任务事件来执行SQL语句删除_edit_lock和_edit_last?

前面跟大家分享了『WordPress如何批量删除wp_postmeta数据表无用的_edit_lock和_edit_last数据&#xff1f;』和『宝塔面板在计划任务中怎么执行SQL语句删除_edit_lock和_edit_last&#xff1f;』&#xff0c;但是有些站长并不是使用宝塔面板&#xff0c;那么我们如何时间定时删…

AIGC:让生成式AI成为自己的外脑

前言 在数字化浪潮席卷全球的今天&#xff0c;人工智能&#xff08;AI&#xff09;已经渗透到了我们生活的方方面面。其中&#xff0c;生成式AI以其独特的魅力&#xff0c;正逐渐改变我们与世界的交互方式。AIGC&#xff08;人工智能生成内容&#xff09;作为生成式AI的重要应用…