根据前序和后序遍历构造二叉树

news2024/12/29 11:51:49

1.题目

这道题是2024-2-22的签到题,题目难度为中等。

考察知识点为递归。

题目链接:889. 根据前序和后序遍历构造二叉树 - 力扣(LeetCode)

给定两个整数数组,preorder 和 postorder ,其中 preorder 是一个具有 无重复 值的二叉树的前序遍历,postorder 是同一棵树的后序遍历,重构并返回二叉树。

如果存在多个答案,您可以返回其中 任何 一个。

2.思路

昨天和家里人玩的太嗨了就只做了题目没有及时更新题解,小小的偷个懒嘿嘿。

题目难点

前两天的题目分别是根据前序与中序遍历序列构造二叉树、从中序与后序遍历序列构造二叉树,因此大体思路我们还是一样的,定义递归函数来构建树。但这道题有一个难点:我们如何确定每棵树的左子树总结点个数leftNum和右子树总结点个数rightNum,前两天我们是根据中序遍历序列来确定leftNum和rightNum的。那么我们重新看一下每一个遍历的顺序序列:

前序遍历数组:[根节点值,(左子树的所有结点值),(右子树的所有结点值)]

中序遍历数组:[(左子树的所有结点值),根节点值,(右子树的所有结点值)]

后序遍历数组:[(左子树的所有结点值),(右子树的所有结点值),根节点值]

很明显我们根据之前的思路只能确定根节点的值,那该怎么办呢?其实这个就要考察我们对树的遍历进一步理解了,下面是我一步一步的思路(可能有点啰嗦,但清晰易懂)。

确定左子树和右子树结点个数

对于同一棵树,它的前序遍历数组下标第一位肯定是根节点,前序遍历数组下标第二位肯定是它的左子结点(这个有点意思了,细品😜)当然我也画了一个简略图方便大家理解。

这样我们是不是可以找到左子树的根节点值了呀,下面这一步是见证奇迹的时候了。对于后序遍历数组,它的下标最后一位肯定是根节点对吧,那么我们是不是可以借助前面得到左子树根节点值来确定它在后序遍历数组的下标索引呢?下面是我画的一个图

有了左子树根节点的值,我们可以利用python的index函数来找到它在后序遍历序列中的下标索引,而后序遍历数组中从遍历开始下标pos_start到左子树根节点下标leftRootIndex这个区间是不是就是左子树区间呢?没错,这样我们就可以求出左子树结点个数leftNum了,然后就可以根据当前数组的pos_start和pos_end来进行相关逻辑相减得到右子树结点个数rightNum。

构建递归函数

同样的,我们需要定义一个递归函数构建我们的树,函数有4个参数,分别是:

pre_start:当前树的前序遍历开始索引

pre_end:当前树的前序遍历结束索引

pos_start:当前树的后序遍历开始索引

pos_end:当前树的后续i办理结束索引

递归核心逻辑

        对于一个正常的遍历序列,它的开始索引肯定是小于等于结束索引的(无论是前序遍历还是后序遍历),因此如果当pre_start>pre_end或pos_start>pos_end的时候,它需要返回None。

如果到了这里你觉得结束了那么不好意思,你这道题要卡住了,为啥,因为这道题我们有一个确定左子树根节点这一操作,根据前面的思路,当前树的左子结点下标索引是排第2位的,即:

preLeftRootIndex = pre_{parent} + 1

因此我们需要对这个preLeftRootIndex进行判断,如果不符合规则(leftRootIndex > pre_end),那么说明这个左子结点是个叶子节点(左子结点没有子结点了),则可以直接返回结点了。否则我们需要确定它在后序遍历数组中的下标索引:

posLeftRootIndex = postorder.index(LeftRootValue)

然后我们利用pos_start和刚才得到的posLeftRootIndex就可以确定左子树的长度了,不理解的还是可以看上面的图。

leftNum = posLeftRootIndex - posStart + 1

rightNum = preEnd - preStart - leftNum

其中,preEnd-preStart表示当前树的所有子树节点个数(leftNum + rightNum)。

到此我们就可以得到两颗子树的下标索引了,接下来就是构建树了,我们还是利用TreeNode来构建结点,然后我们还需要推导两颗子树的4个参数公式:

左子树参数公式

preStart_{son} = preStart_{parent} + 1

preEnd_{son} = preEnd_{parent} + leftNum

posStart_{son} = posStart_{parent}

posEnd_{son} = posStart_{parent} + leftNum - 1

右子树参数公式

preStart_{son} = preStart_{parent} + leftNum + 1

preEnd_{son} = preEnd_{parent}

posStart_{son} = posStart_{parent} + leftNum

posEnd_{son} = posEnd_{parent} - 1

3.代码

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def constructFromPrePost(self, preorder: List[int], postorder: List[int]) -> Optional[TreeNode]:
        # 结点列表的长度
        length = len(preorder)

        # 递归函数,用于构建树
        def build(pre_start,pre_end,pos_start,pos_end):
            # 如果下标索引start>end,则返回None
            if pre_start > pre_end:
                return None
            # 先构建当前树的根节点
            root = TreeNode(preorder[pre_start])
            # 当前树的左子树根节点下标索引(左子结点下标索引)
            pre_leftRoot = pre_start + 1
            # 如果当前索引超出范围,则直接返回结点
            # 说明这个左子树是一个左子结点
            if pre_leftRoot > pre_end:
                return root
            # 求后序遍历数组中左子树根结点的下标索引
            pos_leftRoot = postorder.index(preorder[pre_leftRoot])
            # 左子树所有结点个数
            leftNum = pos_leftRoot - pos_start + 1
            # 右子树所有节点个数
            rightNum = pre_end - pre_start - leftNum
            # 递归构建左子树
            root.left = build(pre_start+1,pre_start+leftNum,pos_start,pos_start+leftNum-1)
            # 递归构建右子树
            root.right = build(pre_start+leftNum+1,pre_end,pos_start+leftNum,pos_end-1)

            return root
        
        return build(0,length-1,0,length-1)


            

                

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

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

相关文章

petalinux_zynq7 驱动DAC以及ADC模块之二:petalinux

petalinux_zynq7 C语言驱动DAC以及ADC模块之一:建立IPhttps://blog.csdn.net/qq_27158179/article/details/136234296在上一篇,建立了ADC和DAC两个IP。这里继续。本文在 petalinux默认配置的基础上,添加了python和qt。再编译出sdk可以给x86主…

Flask——基于python完整实现客户端和服务器后端流式请求及响应

文章目录 本地客户端Flask服务器后端客户端/服务器端流式接收[打字机]效果 看了很多相关博客,但是都没有本地客户端和服务器后端的完整代码示例,有的也只说了如何流式获取后端结果,基本没有讲两端如何同时实现流式输入输出,特此整…

统计图扇形图绘制方法

统计图扇形图绘制方法 常用的统计图有条形图、柱形图、折线图、曲线图、饼图、环形图、扇形图。 前几类图比较容易绘制,饼图环形图绘制较难。 还有一种扇形图的绘制也较难,扇形图的各个变类,饼图、环形图、半圆图、玫瑰图等都是统计图扇形的变…

k8s-heml管理 17

Helm是Kubernetes 应用的包管理工具,主要用来管理 Charts,类似Linux系统的 yum。Helm Chart 是用来封装 Kubernetes 原生应用程序的一系列 YAML 文件。可以在你部署应用的时候自定义应用程序的一些 Metadata,以便于应用程序的分发。 对于应用…

循环购模式:引领电商新时代,重塑消费者价值

在电子商务的浪潮中,循环购模式以其独特的视角和创新的机制,正引领着电商行业进入一个全新的时代。这种模式不仅重塑了消费者的购物体验,更让消费者在享受购物乐趣的同时,实现了个人财富的增值。 一、循环购模式:重新定…

TT语音×个推:流失预测准确率超90%,撬动存量增长个推GeTui 2024-02-23 09:50 浙江

当移动互联网进入存量时代,如何更高效地进行用户全生命周期管理、提升用户生命周期价值,变得尤为重要。TT语音是国内领先的兴趣社交平台,累计注册用户数高达数亿。为了进一步盘活存量用户价值,TT语音从2019年起便与个推合作&#…

Element Plus 的下拉选择器el-option的字体全部蓝色,全部是选中状态

问题 原因 参考官方&#xff1a; Select 选择器 | Element Plus 解决方案1&#xff1a; 给外层el-select增加一个value-key指定值: value-key"ID" <el-select value-key"ID"ref"productName"v-model"selectedProduct.GOODS_DESC"…

eCharts图表点击事件(柱形、label),获取选择项的下标及值

获取选则项的值的话&#xff0c;打印params就能找到了&#xff0c;故主要说明找到对应下标的情况。 柱形点击事件 简单代码 this.myChart echarts.init(this.$refs.chartbox1); this.myChart.off("click"); this.myChart.on("click", (params) > {c…

4.4 MySQL存储1

1、使用前提 安装MySQL数据库&#xff0c;安装pymysql第三方库。 2、使用连接数据库最初步骤 (1) 声明一个连接对象。使用connect()方法声明一个连接对象conn&#xff0c;参数为数据库的一些信息。依次为主机名、用户名、密码、端口号&#xff1b; (2) 获得游标。使用cursor…

intellij idea创建spring项目时没有java 8

一、 引入 当我们用file–》new–》project创建一个项目时&#xff0c;会遇到下面的情况(如图二所示&#xff09;&#xff0c; 图一 图二 java版本仅有21和17可选&#xff0c;而国内大部分还在用java 8 版本&#xff0c;会导致项目无法启动。 二、解决办法 点击serverUrl进…

mysql-多表查询-外连接

一、外连接查询语法 &#xff08;1&#xff09;左外连接 select 所要查询的内容 from 左表 left outer join 右表 on 条件; &#xff08;2&#xff09;右外连接 select 所要查询的内容 from 左表 right outer join 右表 on 条件; 二、示例 用以下两张表示例 左外连接 右外…

3.测试教程 - 基础篇

文章目录 软件测试的生命周期软件测试&软件开发生命周期如何描述一个bug如何定义bug的级别bug的生命周期如何开始第一次测试测试的执行和BUG管理产生争执怎么办&#xff08;处理人际关系&#xff09; 大家好&#xff0c;我是晓星航。今天为大家带来的是 测试基础 相关的讲解…

戏曲文化苑|戏曲文化苑小程序|基于微信小程序的戏曲文化苑系统设计与实现(源码+数据库+文档)

戏曲文化苑小程序目录 目录 基于微信小程序的戏曲文化苑系统设计与实现 一、前言 二、系统功能设计 三、系统实现 1、微信小程序前台 2、管理员后台 &#xff08;1&#xff09;戏曲管理 &#xff08;2&#xff09;公告信息管理 &#xff08;3&#xff09;公告类型管理…

开源免费大模型框架自己训练可根据关键词提示绘图的软件

开源免费大模型框架自己训练可根据关键词提示绘图的软件!大家都知道&#xff0c;市面上那些可以支持这种业务的大模型都是收费的&#xff0c;如果你是一个资深的大模型爱好者&#xff0c;并且有自己的打算和预算&#xff0c;想自己训练一套属于自己的大模型软件来完成日常的绘图…

什么是MapReduce

1.1 MapReduce到底是什么 Hadoop MapReduce是一个软件框架&#xff0c;基于该框架能够容易地编写应用程序&#xff0c;这些应用程序能够运行在由上千个商用机器组成的大集群上&#xff0c;并以一种可靠的&#xff0c;具有容错能力的方式并行地处理上TB级别的海量数据集。这个定…

编程学习线上提问现场解答流程,零基础学编程从入门到精通

编程学习线上提问现场解答流程 一、前言 之前给大家分享的一款中文编程工具&#xff0c;越来越多的学员使用这个工具学习编程。 在学习中有疑难问题寻求解答流程 1、可以在本平台留言或发私信联系老师 2、可以在群提问及时解答问题 3、通过线上会议的方式&#xff0c;电脑…

2024年必备原型设计工具盘点,助你成为设计大神

原型设计是 UI/UX 设计中至关重要的一步&#xff0c;就像用户体验中的其他环节一样&#xff0c;有无数的原型工具可以帮助你完成原型设计。 如果市场上有太多的原型设计工具让你不知所措&#xff0c;不知道选择哪一个&#xff0c;恭喜你&#xff0c;这个原型设计工具的集合是为…

go-zero微服务入门教程

go-zero微服务入门教程 本教程主要模拟实现用户注册和用户信息查询两个接口。 准备工作 安装基础环境 安装etcd&#xff0c; mysql&#xff0c;redis&#xff0c;建议采用docker安装。 MySQL安装好之后&#xff0c;新建数据库dsms_admin&#xff0c;并新建表sys_user&#…

openEuler安装MySQL客户端、openEuler安装MySQL-client、openEuler部署MySQL-client

MySQL客户端下载链接&#xff1a;https://downloads.mysql.com/archives/community/ mysql-community-client-5.7.30-1.el7.x86_64.rpm mysql-community-common-5.7.30-1.el7.x86_64.rpm mysql-community-libs-5.7.30-1.el7.x86_64.rpm 3个必选 8.0.22以上的版本是4个&…

个人博客系列-项目部署-nginx(3)

使用Nginx uwsgi进行部署django项目 一. 检查项目是否可以运行 启动项目 python manage.py runserver 0.0.0.0:8099输入ip:8099 查看启动页面 出现上述页面表示运行成功 二. 安装uwsgi并配置 2.1 下载uwsgi pip install uwsgi新建文件test.py写入内容&#xff0c;测试一…