目录

1  另一棵树的子树 

 1) 题目描述

示例1:

示例2:

2) 算法解析

3) 代码

2  二叉树的遍历

1) 问题描述

2) 算法解析

3) 代码

3  总结  


1  另一棵树的子树 

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


 1) 题目描述

  给你两棵二叉树 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 这棵树中是否有 subRoot 这棵树,不管是相同的树,还是左子树中有与subRoot 相同的树或者是在右子树中有与 subRoot 相同的树,subRoot 都算是 root 的子树。


2) 算法解析

  该题目可以采用递归算法来解决。这道题的解决需要使用到前一篇文章里的相同的树的算法,因为判断 subRoot 是否是 root 的子树,本质上就是判断 root 里是否有与 subRoot 相同的树,具体算法思想描述如下:
  该递归算法可以抽象为 root 的左子树里是否有与 subRoot 相同的树或者右子树里是否有与 subRoot 相同的树,这个就是递归解决该问题的过程。边界条件共有两条:(1) 如果 root 本身是一棵空树,那么 root 里肯定没有与 subRoot 相同的树,直接返回 false;(2) 如果 root 这棵树本身就是与 subRoot 相同的树,说明 subRoot 是 root 的一棵子树,那就返回 true。


3) 代码

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) 
{//如果root为空,那就返回falseif (root == NULL){return false;}//如果两个结点对应的树是相同的树,返回trueif (isSameTree(root, subRoot)){return true;}//判断subRoot是否是左子树或者右子树的子树return isSubtree(root->left, subRoot) || isSubtree(root->right, subRoot);
}

2  二叉树的遍历

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


1) 问题描述

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

  这里看似是一个简单的前序遍历,但是其实没有那么简单,我们来看一下函数头部:

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

  可以看到其返回值为 int* ,也就是一个指针,并不像之前我们写过的前序遍历一样返回值为 void。实际上这里是需要返回一个存储了节点前序遍历值的数组,所以返回值才为 int*。


2) 算法解析

  这里最大的难点就在与如何将前序遍历的结果存储在数组里面,而且所给的函数头部里面也有一个 returnSize 参数,通过名字可以看出来,该参数的作用实际上就是返回数组的大小,所以我们不仅需要将数组返回,还得计算数组中有多少元素,也就是二叉树里面有多少节点。所以我们需要首先计算二叉树里面节点的个数(在链式二叉树文章中提到过相关操作的实现),所以这里总共需要 3 个函数:

(1) TreeSize函数:用来计算二叉树里面节点的个数。

(2) PreOrder函数:用来进行前序遍历,将结果存储在数组中。

(3) preorderTraversal函数:用来创建数组,返回存储结果的数组。

  接下来我们来讲解如何将前序遍历的结果存储在数组中。

  可能开始我们想的是按照前序遍历的代码,只需将打印的地方改为向数组中存储值即可:

void PreOrder(TreeNode* root, int* arr)
{int i = 0;if (root == NULL){return;}arr[i] = root->val;i++;PreOrder(root->left, arr);PreOrder(root->right, arr);
}

但是这样会存在一个问题,就是在不断递归的过程中,每次进入新的递归的时候,里面的 i 都会变成0,也就是总是往 arr[0] 位置存储前序遍历的结果,这里借助函数栈帧(每次调用函数时,会新开辟的一块空间,每个函数的空间是独立的)的概念来解释:

可以看到每次调用PreOrder函数,都会新开辟一块空间,所以其实里面的 i 都是属于不用空间的,一个 i 改变并不会影响另一个函数里面的 i ,所以每次递归调用函数 i 都是为 0 的。

  那么要想在递归过程中改变这个下标,我们就需要传递一个整形的地址,让其能够找到存储 arr 下标的空间,让存储空间里面的值改变,就会让下标随着递归的而改变了

//arr为数组收元素的地址,pi为存储arr数组下标的地址
void PreOrder(TreeNode* root, int* arr, int* pi)
{if (root == nullptr){return;}arr[(*pi)++] = root->val;PreOrder(root->left);PreOrder(root->right);
}

这里就可以通过一个指针变量 pi 来指向存储 arr 数组下标的空间(传参时传递一个值为 0 的整型的地址即可), 这样通过 pi 就可以间接改变 arr 数组中的值了。


3) 代码

typedef struct TreeNode TreeNode;//先计算树的结点个数,依结点个数开辟数组空间int TreeSize(TreeNode* root){if (root == NULL){return 0;}return 1 + TreeSize(root->left) + TreeSize(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 = TreeSize(root);int* arr = (int*)malloc(sizeof(int) * (*returnSize));if (arr == NULL){perror("malloc fail!\n");exit(1);}int n = 0;PreOrder(root, arr, &n);return arr;
}

3  总结  

  在该题目中,我们解决了如何在递归过程中向数组中存储数据的问题。只需用一个指针变量间接改变即可。所以以后如果遇到类似问题,一定要想到利用指针来改变下标。

  当然,除了前序遍历,还有中序遍历和后序遍历,在讲解完前序遍历之后,相信这两个遍历也很简单了,可以自己尝试一下:
中序遍历https://leetcode.cn/problems/binary-tree-inorder-traversal/代码:

typedef struct TreeNode TreeNode;//返回树的结点个数int TreeSize(TreeNode* root){if (root == NULL){return 0;}return 1 + TreeSize(root->left) + TreeSize(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 = TreeSize(root);int* arr = (int*)malloc(sizeof(int) * (*returnSize));if (arr == NULL){perror("malloc fail!\n");exit(1);}int n = 0;InOrder(root, arr, &n);return arr;
}

后序遍历https://leetcode.cn/problems/binary-tree-postorder-traversal/description/代码:

typedef struct TreeNode TreeNode;//求节点个数int TreeSize(TreeNode* root){if (root == NULL){return 0;}return 1 + TreeSize(root->left) + TreeSize(root->right);}//二叉树的后序遍历并将遍历结果保存到数组中
void PostOrder(int* arr, TreeNode* root, int* i)
{if (root == NULL){return;}//遍历左子树PostOrder(arr, root->left, i);//遍历右子树PostOrder(arr, root->right, i);arr[(*i)++] = root->val;}int* postorderTraversal(struct TreeNode* root, int* returnSize) {*returnSize = TreeSize(root);//根据二叉树节点空间开辟数组int* arr = (int*)malloc(sizeof(int) * (*returnSize));int i = 0;PostOrder(arr, root, &i);return arr;
}

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

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

相关文章

配置Hadoop集群

Hadoop的运行模式 本地运行:在一台单机上运行,没有分布式文件系统,直接读写本地操作系统的文件系统。特点:不对配置文件进行修改,Hadoop 不会启动 伪分布式:也是在一台单机上运行,但用不同的 …

python办公自动化--数据可视化(pandas+matplotlib)--生成条形图和饼状图

前言 前几天我们学习了pandas读取数据,还学习了如何用patplotlib绘制柱状图和折线图。 今天我们继续学习,如何绘制条形图和饼状图。 一、课程回顾-pandas读取数据 1.示例数据文件 这里我们用到的依旧是d盘底下的这个excel工作簿,这个工作簿…

基于大模型的结节性甲状腺肿诊疗全流程预测与方案研究报告

目录 一、引言 1.1 研究背景与目的 1.2 研究意义 1.3 国内外研究现状 二、大模型预测原理与方法 2.1 相关大模型概述 2.2 数据收集与预处理 2.3 模型训练与验证 三、术前预测与评估 3.1 结节性质预测 3.1.1 良恶性判断 3.1.2 与传统诊断方法对比 3.2 手术风险预测…

不同开发语言对字符串的操作

一、字符串的访问 Objective-C: 使用 characterAtIndex: 方法访问字符。 NSString *str "Hello, World!"; unichar character [str characterAtIndex:0]; // 访问第一个字符 H NSLog("%C", character); // 输出: H NSString 内部存储的是 UTF-16 编…

Java开发者如何接入并使用DeepSeek

目录 一、准备工作 二、添加DeepSeek SDK依赖 三、初始化DeepSeek客户端 四、数据上传与查询 五、数据处理与分析 六、实际应用案例 七、总结 【博主推荐】:最近发现了一个超棒的人工智能学习网站,内容通俗易懂,风格风趣幽默&#xff…

S19文件格式详解:汽车ECU软件升级中的核心镜像格式

文章目录 引言一、S19文件格式的起源与概述二、S19文件的核心结构三、S19在汽车ECU升级中的应用场景四、S19与其他格式的对比五、S19文件实例解析六、工具链支持与安全考量七、未来趋势与挑战结语引言 在汽车电子控制单元(ECU)的软件升级过程中,S19文件(也称为Motorola S-…

CTF杂项——[suctf 2019]签到题

base64转图片 可以直接用随波逐流 得到flag SUCTF{ffffffffT4nk}

【Python】整数除法不正确,少1的问题,以及有关浮点数转换的精度问题

1. 问题 今天在做leetcode 不同路径 的时候发现了个问题 对于m53 n4class Solution:def uniquePaths(self, m: int, n: int) -> int:rlt 1for i in range(0, m-1):rlt * (m n - 2 - i)for i in range(0, m-1):rlt / (i 1)return int(rlt)为什么这个结果是 26234class S…

AI无代码平台

以下是目前支持快速开发产品的高生产力免费AI无代码平台推荐,按功能和适用场景分类: 一、全栈应用开发类 Bolt.DIY DeepSeek-R1 无需编写代码即可开发全栈应用,提供免费API和无速率限制,支持AI编码助手与自动化流程 。 优势&…

Gini系数的应用 - 指标波动贡献分析

基尼系数的定义 基尼系数是衡量数据分布不均衡程度的指标,取值范围在0到1之间: 0 表示完全均衡(所有值相等)。1 表示完全不均衡(所有值集中在一个点)。 基尼系数的计算公式 假设有 n n n 个数据点&…

第一节: 网络基础与参考模型

深入理解OSI七层模型与TCP/IP四层模型:网络工程师的入门指南 在网络通信的世界中,OSI七层模型和TCP/IP四层模型是理解网络架构的基础。无论是配置路由器、排查网络故障,还是设计复杂的网络系统,掌握这些模型的分层结构及其功能都是必不可少的。本文将从新手角度出发,深入…

HTTP拾技杂谈

HTTP拾技杂谈 简单聊聊HTTP中的那些东西 文章目录 HTTP拾技杂谈前言HTTP协议1.请求从客户端到服务器端的4个步骤一般客户端请求如下:服务端响应如下 2.Keep-AliveHTTP方法Cookie 总结 前言 超文本传输协议(Hypertext Transfer Protocol ,HT…

用Deepseek写一个五子棋微信小程序

在当今快节奏的生活中,休闲小游戏成为了许多人放松心情的好选择。五子棋作为一款经典的策略游戏,不仅规则简单,还能锻炼思维。最近,我借助 DeepSeek 的帮助,开发了一款五子棋微信小程序。在这篇文章中,我将…

自然语言处理:最大期望值算法

介绍 大家好,博主又来给大家分享知识了,今天给大家分享的内容是自然语言处理中的最大期望值算法。那么什么是最大期望值算法呢? 最大期望值算法,英文简称为EM算法,它的核心思想非常巧妙。它把求解模型参数的过程分成…

【从零开始学习计算机科学】计算机体系结构(一)计算机体系结构、指令、指令集(ISA)与量化评估

【从零开始学习计算机科学】计算机体系结构(一)计算机体系结构、指令、指令集(ISA)与量化评估 概论计算机体系结构简介计算机的分类并行体系结构指令集体系结构(ISA)分类存储器寻址寻址模式操作数大小指令ISA的编码程序的优化计算机体系结构量化评估存储器体系结构概论 …

Electron使用WebAssembly实现CRC-32 常用标准校验

Electron使用WebAssembly实现CRC-32 常用标准校验 将C/C语言代码,经由WebAssembly编译为库函数,可以在JS语言环境进行调用。这里介绍在Electron工具环境使用WebAssembly调用CRC-32 常用标准格式校验的方式。 CRC-32 常用标准校验函数WebAssembly源文件…

Docker基础篇——Ubuntu下Docker安装

大家好我是木木,在当今快速发展的云计算与云原生时代,容器化技术蓬勃兴起,Docker 作为实现容器化的主流工具之一,为开发者和运维人员带来了极大的便捷 。下面我们一起进行Docker安装。 Docker的官方Ubuntu安装文档,如…

第五课:Express框架与RESTful API设计:技术实践与探索

在使用Node.js进行企业应用开发,常用的开发框架Express,其中的中间件、路由配置与参数解析、RESTful API核心技术尤为重要,本文将深入探讨它们在应用开发中的具体使用方法,最后通过Postman来对开发的接口进行测试。 一、Express中…

mitmproxy配合Wireshark 抓包分析

Mitmproxy 是一款非常强大的 交互式 HTTP 代理 工具,它被广泛应用于 Web 开发、API 调试、安全测试 等领域。与 Wireshark 侧重于被动监听网络流量不同,Mitmproxy 更像一个 主动的中间人,可以拦截、检查、修改和重放 HTTP/HTTPS 流量&#xf…

Varlens(手机上的单反)Ver.1.9.3 高级版.apk

Varlens 是一款专业级手机摄影软件,旨在通过丰富的功能和高自由度参数调节,让手机拍摄效果媲美微单相机。以下是核心功能总结: 一、核心功能 专业拍摄模式 支持手动/自动/程序模式,可调节ISO、快门速度、EV、白平衡等参数27 提供…