【刷题】144. 二叉树的前序遍历

news2024/9/22 23:24:14

144. 二叉树的前序遍历

  • 一、题目描述
  • 二、示例
  • 三、实现
  • 总结


144. 二叉树的前序遍历

一、题目描述

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

三、实现

前序遍历很容易想到以下代码:

void PreOrder(BTNode* root)
{
	if (root == NULL)
	{
		//printf("NULL ");
		return;
	}

	printf("%c ", root->data);
	PreOrder(root->left);
	PreOrder(root->right);
}

但考虑到该题的接口设计:

/**
 * Note: The returned array must be malloced, assume caller calls free().
 */
int* preorderTraversal(struct TreeNode* root, int* returnSize) {

}

该函数返回接口前序遍历结果的数组,因此我们需要用上面前序遍历的递归实现方式把遍历的值存到数组里,并且这个数组是由我们malloc申请的,由调用preorderTraversal的人free释放。

我们先用malloc申请空间,但是申请多大空间?上面提供的函数接口还需要retrunSize作为返回值。这便需要我们先便利求出树中结点的总数。

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

/**
 * Note: The returned array must be malloced, assume caller calls free().
 */
int* preorderTraversal(struct TreeNode* root, int* returnSize) {
    // 得到树中结点总数:一方面作为retrunSize返回值,另一方面作为下面申请空间大小的依据
	int size = BinaryTreeSize(root);
	printf("size:%d\n", size);
	int* preorder = (int*)malloc(size * sizeof(int));
}

申请完空间以后,我们需要将前序遍历序列放到我们申请的空间中,考虑到前序遍历我们使用递归实现的,因此我们需要将该过程放在子函数中:

/**
 * Note: The returned array must be malloced, assume caller calls free().
 */
void _preorderTraversal(struct TreeNode* root, int* preorder, int* pIndex)
{
	if (root == NULL)
	{
		return;
	}
	
	printf("%d ", root->val);
	preorder[(*pIndex)++] = root->val;
	_preorderTraversal(root->left, preorder, pIndex);
	_preorderTraversal(root->right, preorder, pIndex);
}
int* preorderTraversal(struct TreeNode* root, int* returnSize) {
	// 得到树中结点总数:一方面作为retrunSize返回值,另一方面作为下面申请空间大小的依据
	int size = BinaryTreeSize(root);
	printf("size:%d\n", size);
	int* preorder = (int*)malloc(size * sizeof(int));
	int index = 0;
	_preorderTraversal(root, preorder, &index);
	*returnSize = size;
	return preorder;
}

在子函数_preorderTraversal中我们利用前序遍历递归将前序遍历序列放到我们申请的空间里。

值得说的是该函数的接口中,我们需要放到我们申请的数组的索引值。该索引值是指针传参,为的就是递归的过程中左子树递归时的索引值和右子树递归时的索引值不同。假设我们使用值传递索引,在前序遍历的代码中,我们先递归左子树,左子树递归完以后返回到当前层,然后准备递归右子树时索引值没有变化,这就是代码中的bug。

// 错误的索引值index
void _preorderTraversal(struct TreeNode* root, int* preorder, int index)
{
	if (root == NULL)
	{
		return;
	}
	
	printf("%d ", root->val);
	preorder[index++] = root->val;
	_preorderTraversal(root->left, preorder, index);
	_preorderTraversal(root->right, preorder, index);
}

完整代码:

/**
 * 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 BinaryTreeSize(struct TreeNode* root)
{
	/*
	if (root == NULL)
	{
		return 0;
	}
	return 1 + BinaryTreeSize(root->left) + BinaryTreeSize(root->right);
	*/
	return root == NULL ? 0 : BinaryTreeSize(root->left) + BinaryTreeSize(root->right) + 1;
}
void _preorderTraversal(struct TreeNode* root, int* preorder, int* pIndex)
{
	if (root == NULL)
	{
		return;
	}
	
	printf("%d ", root->val);
	preorder[(*pIndex)++] = root->val;
	_preorderTraversal(root->left, preorder, pIndex);
	_preorderTraversal(root->right, preorder, pIndex);
}
int* preorderTraversal(struct TreeNode* root, int* returnSize) {
	// 得到树中结点总数:一方面作为retrunSize返回值,另一方面作为下面申请空间大小的依据
	int size = BinaryTreeSize(root);
	*returnSize = size;
	printf("size:%d\n", size);

	int* preorder = (int*)malloc(size * sizeof(int));
	int index = 0;
	_preorderTraversal(root, preorder, &index);
	return preorder;
}

总结

总结:

1.在外层接口不方便递归时,将递归过程封装成子函数的思想可以借鉴。这让我想到了远古的回忆,在 利用短路表达式判断一个数是否是素数 的递归实现中,也是将递归的代码封装成一个子函数。

2.第二个注意点就是索引值的传递,我们需要传递指针,保证函数内部使用的指针指向的值同步更新。这一点在求二叉树中结点的个数接口中也有思想体现:

void BinaryTreeSize(BTNode* root, int* pn)
{
	if (root == NULL)
	{
		return;
	}

	++(*pn);
	BinaryTreeSize(root->left, pn);
	BinaryTreeSize(root->right, pn);
}

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

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

相关文章

第十五章行为性模式—命令模式

文章目录 命令模式解决的问题结构实例存在的问题适用场景 JDK 源码 - Runnable 行为型模式用于描述程序在运行时复杂的流程控制,即描述多个类或对象之间怎样相互协作共同完成单个对象无法单独完成的任务,它涉及算法与对象间职责的分配。行为型模式分为类…

OW-DETR: Open-world Detection Transformer(论文翻译)

文章目录 OW-DETR: Open-world Detection Transformer摘要1.介绍2.开放世界检测的transformer2.1整体架构2.2.多尺度上下文编码2.3.注意力驱动的伪标签2.4 新类分类2.5.前景物体2.6.训练与推理 3.实验3.1.最新技术水平比较3.2.增量目标检测3.3 消融实验 4.与现有技术的关系5.结…

【干货收藏】 隔离驱动SLMi335/SLMi335H 电路方案分享

数明深力科SLMi33X系列SLMi335/SLMi335H首款单通道带DESAT保护功能的IGBT/SiC隔离驱动器。内置快速去饱和(DESAT) 故障检测功能、米勒钳位功能、漏极开路故障反馈、软关断功能以及可选择的自恢复模式,兼容光耦隔离驱动器。 SLMi33X系列SLMi335/SLMi335H的DESAT阈值…

如何搭建高质量的 B 端产品帮助体系?

在B2B市场中,产品的质量和支持服务对于企业的成功至关重要。帮助中心是B2B企业提供优质支持服务的重要组成部分。那么,如何搭建高质量的B端产品帮助体系呢?本文将为大家介绍一些关键的步骤和方法。 一、了解用户需求 首先,要搭建…

【ZYNQ】QSPI Flash 固化程序全攻略

普通的 FPGA 一般是可以从 Flash 启动,或者被动加载,ZYNQ 的启动是由 ARM 主导的,包括 FPGA 程序的加载,ZYNQ 启动一般为最少两个步骤,在 UG585 中也有介绍。 Stage 0:BootROM 阶段 在 ZYNQ 上电复位或者热…

前端异步请求并解决跨域问题(Ajax+axios框架)、后端响应多个数据(JSON)

目录 一、前后端同步异步请求 1.同步请求: 2.异步请求: 3.跨域问题(前端问题) 4.axios框架(封装后) 二、后端向前端响应多个数据-JSON 一、前后端同步异步请求 1.同步请求: 发送一个请求…

【Java多线程进阶】CAS机制

前言 CAS指的是Compare-And-Swap(比较与交换),它是一种多线程同步的技术,常用于实现无锁算法,从而提高多线程程序的性能和扩展性。本篇文章具体讲解如何使用 CAS 的机制以及 CAS 机制带来的问题。 目录 1. 什么是CAS&…

《机器学习算法竞赛实战》-chapter4特征工程

《机器学习算法竞赛实战》学习笔记,记录一下自己的刷题过程,详细的内容请大家购买作者的书籍查阅。 特征工程 特征工程是算法竞赛中工作量最大,决定参赛者能否拿到较好名次的关键部分。吴恩达老师说过:“机器学习在本质上还是特…

Maven Compile时报错 [ERROR] [X Group Enforcer Rules] find DuplicateClasses

类冲突 [ERROR] [Ctrip Group Enforcer Rules] find DuplicateClasses Found in: net.jpountz.lz4:lz4:jar:1.3.0:compile org.lz4:lz4-java:jar:1.7.1:compile Duplicate classes: net/jpountz/xxhash/AbstractStreamingXXHash32Java.class net/jpountz/lz4/LZ4BlockInputStre…

Arduino+ESP8266 MCU开发板 ----带你开发 (TCP)双向局域网通信 项目-----可开发成为小远程控制

目录 本次需要下载的代码链接: 文章项目引用:本次实现可依据之前的文章就行举一反三的操作 本次开发项目步1:下载Aeduino软件 本次开发项目步2: 更替代码片段1 第13行 代替账号和密码 更替代码片段2 第20行 …

软件科技项目验收有哪些注意事项?第三方软件验收测试的好处在哪?

软件科技项目的验收是软件生产周期中非常重要的一个环节。它主要目的是验证软件产品是否满足用户需求,达到预期的质量和性能要求。因此,在进行软件科技项目验收时,有一些注意事项需要遵循。 一、软件科技项目验收的注意事项 1、明确验收标准…

JS使用随机数生成随机验证码

一 随机数测试 在JavaScript中,我们可以使用random( )方法来生成0~1的一个随机数。random,就是“随机”的意思。需要注意的是,这里的0~1包含0但不包含1,也就是[0, 1)。在…

ubuntu20.04 ROS 环境下使用velodyne激光雷达

ROS 环境下使用velodyne激光雷达 系统版本:ubuntu 20.04 ROS版本:noetic 激光雷达型号:velodyne VLP-16 1.系统环境配置 sudo apt install ros-noetic-velodyne #安装ROS依赖 mkdir-p velodyne_ws/src …

PyQt重绘事件处理函数paintEvent

PyQt中的重绘和Windows编程中的重绘差不多,但是Qt的重绘更有特色,更加智能。基础部件类QWidget提供的paintEvent函数是一个纯虚函数,继承它的子类想用它,就必须重新实现它。下列4种情况会发生重绘事件: (1…

全网最全的Salesforce营销云管理员认证考点梳理!

Marketing Cloud管理员认证适用于在Marketing Cloud套件中具有设置和维护各种模块(Studios/Builders)和功能的经验的营销专业人员。Salesforce建议备考者拥有3到6个月的Marketing Cloud管理员和数字营销人员实践经验。 营销云管理员认证 考试内容&#…

IOS发布:App Store Connect Operation Error。SDK Version Issue.

错误描述: App Store Connect Operation Error SDK Version Issue. This app was built with the iOS 15.0 SDK. all iOS apps submitted to the App Store must be built with the iOS 16.1 SDK or later, included in Xcode 14.1 or later. 问题原因&#xf…

ESP32 的多种睡眠模式以及如何让 ESP32 进入深度睡眠模式

ESP32 因其 BLE 兼容性功能以及更低的成本而受到广泛关注。它还带有 32 个 GPIO 引脚和一个 32 位双核 CPU。虽然,它提供了很多功能,但在正常使用模式下似乎很耗电。当应用程序由市电供电时,没有急事,但是当它们由电池供电时,我们必须非常注意 ESP32 的功耗。 ESP32 提供…

SQL使用技巧(6)HIVE开窗函数

专题:SQL使用技巧——实践是检验SQL函数的唯一标准 一.构建数据二.排序开窗三.sum开窗(重点内容)3.1累加与求和3.2窗口表达式3.3场景模拟 四.count开窗4.1计数规则4.2计数与排序 五.max和min开窗六.lead和lag开窗七.first_value和last_value开…

RabbitMq创建交换机和队列

1. 网页登录 IP:1572 2. 输入登录账号密码 admin admin 3. 点击Exchanges 添加交换机Platform_AlarmEngineInterface 和Rg_Platform_AlarmEngineInterface ,Type选择topic 4. 添加队列 VIDEO_Alarm_platform、watch_ftp、RG_VIDEO_Alarm_platform、RG_VIDEO_…

远程进入服务器界面黑屏如何处理?

​  远程登录服务器出现黑屏是很常见的问题,可能是由于多种原因引起的。但不管是哪种原因,当远程连接成功,进入桌面显示黑屏都会让用户感到困扰,无法正常使用服务器。下面我们将为您介绍一些常见的解决方法。 1. 重启远程桌面服…