LC 106.从中序与后序遍历序列构造二叉树

106. 从中序与后序遍历序列构造二叉树

给定两个整数数组 inorderpostorder ,其中 inorder 是二叉树的中序遍历, postorder 是同一棵树的后序遍历,请你构造并返回这颗 二叉树

示例 1:

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

示例 2:

输入: inorder = [-1], postorder = [-1]
输出:[-1]

提示:

  • 1 ≤ i n o r d e r . l e n g t h ≤ 3000 1 \leq inorder.length \leq 3000 1inorder.length3000
  • postorder.length == inorder.length
  • − 3000 ≤ i n o r d e r [ i ] , p o s t o r d e r [ i ] ≤ 3000 -3000 \leq inorder[i], postorder[i] \leq 3000 3000inorder[i],postorder[i]3000
  • inorderpostorder 都由 不同 的值组成
  • postorder 中每一个值都在 inorder
  • inorder 保证是树的中序遍历
  • postorder 保证是树的后序遍历

解法一(递归+分治+Map哈希)

思路分析:

  1. 对于该题,首先思考;中序遍历为:左中右,后序遍历为:左右中,因此通过后序遍历可以确认二叉树的根节点,然后通过根节点可以对中序遍历进行切割成:左中序右中序;然后根据得到的左中序长度,可以对后序遍历进行切割成:左后序右后序
  2. 以此类推,通过递归分治的方式,可以从根节点建立一个二叉树。
  3. 同时思考递归的参数和返回值,因为题目要求构造一个二叉树,所以 返回值类型为TreeNode,然后对于递归的参数则包括,中序遍历数组、后序遍历数组、中序数组起始位置、中序数组末尾位置、后序数组起始位置、后序数组末尾位置。
  4. 对于递归的边界条件,则当后序遍历数组为null时,返回null,当由后序遍历索引起始及末尾位置得;数组长度为1时,直接返回
  5. 对于递归的过程,则是构造中间节点,以及递归构造左右节点
  6. 同时对于如何根据后序数组,对中序数组进行分割,可以使用Map哈希表的方式,避免对中序数组进行反复查询。

实现代码如下:

class Solution {public TreeNode buildTree(int[] inorder, int[] postorder) {if (postorder == null)return null;	// 边界条件// 构造哈希表Map<Integer, Integer> inMap = new HashMap<>();for (int i = 0; i < inorder.length; i++) {inMap.put(inorder[i], i);}return doBuildTree(inorder, postorder, inMap, 0, inorder.length-1, 0, postorder.length-1);}private TreeNode doBuildTree(int[] inorder, int[] postorder, Map<Integer, Integer> inMap, int inS, int inE, int postS, int postE) {if (inE < 0 || postE < 0 || inS > inE || postS > postE || inS >= inorder.length || postS >= postorder.length) // 考虑边界问题return null;// 根据后序遍历数组 末尾索引 获取该子树根节点值int rootValue = postorder[postE];TreeNode node = new TreeNode(rootValue);	// 构造二叉树if (postS == postE)		// 若此时后序数组 起始索引和末尾索引相等 说明为叶子节点return node;	// 直接返回// 根据根节点值 对中序数组进行分割 获取分割位置索引int index = inMap.get(rootValue);// 递归获取左右子树node.left = doBuildTree(inorder, postorder, inMap, inS, index-1, postS, postS+index-1-inS);node.right = doBuildTree(inorder, postorder, inMap, index+1, inE, postS+index-inS, postE-1);return node;}
}

提交结果如下:

解答成功:
执行耗时:2 ms,击败了62.35% 的Java用户
内存消耗:43.5 MB,击败了13.55% 的Java用户

复杂度分析:

  • 时间复杂度: O ( n + m ) O(n+m) O(n+m),需要遍历数组
  • 空间复杂度: O ( n + m ) O(n+m) O(n+m),考虑递归对空间的消耗

优化解法一

思路分析:

  1. 通过对解法一代码的执行流程,发现递归函数doBuildTree中的inorder参数可以省略
  2. 且对于doBuildTree函数中的边界问题判断,由于初始inEPostE均为len-1inSpostS初始为0,因此对于inE < 0的判断与inS >= inorder.length的判断包含在inS > inE中,可省略

实现代码如下:

class Solution {public TreeNode buildTree(int[] inorder, int[] postorder) {if (postorder == null)return null;	// 边界条件// 构造哈希表Map<Integer, Integer> inMap = new HashMap<>();for (int i = 0; i < inorder.length; i++) {inMap.put(inorder[i], i);}return doBuildTree(postorder, inMap, 0, inorder.length-1, 0, postorder.length-1);}private TreeNode doBuildTree(int[] postorder, Map<Integer, Integer> inMap, int inS, int inE, int postS, int postE) {if (inS > inE || postS > postE) // 考虑边界问题return null;// 根据后序遍历数组 末尾索引 获取该子树根节点值int rootValue = postorder[postE];TreeNode node = new TreeNode(rootValue);	// 构造二叉树if (postS == postE)		// 若此时后序数组 起始索引和末尾索引相等 说明为叶子节点return node;	// 直接返回// 根据根节点值 对中序数组进行分割 获取分割位置索引int index = inMap.get(rootValue);// 递归获取左右子树node.left = doBuildTree(postorder, inMap, inS, index-1, postS, postS+index-1-inS);node.right = doBuildTree(postorder, inMap, index+1, inE, postS+index-inS, postE-1);return node;}
}

提交结果如下:

解答成功:
执行耗时:2 ms,击败了62.35% 的Java用户
内存消耗:43.6 MB,击败了10.93% 的Java用户

复杂度分析:

  • 时间复杂度: O ( n + m ) O(n+m) O(n+m),遍历中序数组和后序数组
  • 空间复杂度: O ( n + m ) O(n+m) O(n+m),考虑每层递归传递参数对空间消耗。

解法二(递归+分治+Map)

思路分析:

  1. 跟据官方题解,将中序数组、后序数组,以及提交查询的Map变量,均改为全局遍历,即不需要作为递归函数参数,可在递归函数内访问。
  2. 因为后序遍历中,最后一个元素为子树的根节点,所以先递归获取右子树,再递归获取左子树

实现代码如下:

class Solution {int[] inorder;		// 中序遍历数组int[] postorder;	// 后序遍历数组Map<Integer, Integer> inMap;	// 中序遍历数组 索引表int postIndex;public TreeNode buildTree(int[] inorder, int[] postorder) {if (postorder == null)return null;	// 边界条件this.inorder = inorder;this.postorder = postorder;postIndex = postorder.length-1;// 构造哈希表inMap = new HashMap<>();for (int i = 0; i < inorder.length; i++) {inMap.put(inorder[i], i);}return doBuildTree(0, inorder.length-1);}private TreeNode doBuildTree(int inLeft, int inRight) {if (inLeft > inRight)	// 说明此时为空树return null;int value = postorder[postIndex];	// 根据postIndex 来确定当前子树 中节点值TreeNode node = new TreeNode(value);// 根据 中间节点值 获取分割中序数组索引int index = inMap.get(value);postIndex--;	// 移动所指向的根节点// 先获取右子树node.right = doBuildTree(index+1, inRight);// 再获取左子树node.left = doBuildTree(inLeft, index-1);return node;}
}

提交结果如下:

解答成功:
执行耗时:1 ms,击败了99.58% 的Java用户
内存消耗:43.2 MB,击败了32.11% 的Java用户

复杂度分析:

  • 时间复杂度: O ( n ) O(n) O(n)n表示树的节点个数
  • 空间复杂度: O ( n ) O(n) O(n),需要使用 O ( n ) O(n) O(n)的空间存储哈希表,同时 O ( h ) O(h) O(h)的空间进行递归(即二叉树的高度),且h < n

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

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

相关文章

突破编程_C++_网络编程(OSI 七层模型(物理层与数据链路层))

1 OSI 七层模型概述 OSI&#xff08;Open Systems Interconnection&#xff09;七层模型&#xff0c;即开放系统互联参考模型&#xff0c;起源于 20 世纪 70 年代和 80 年代。随着计算机网络技术的快速发展和普及&#xff0c;不同厂商生产的计算机和网络设备之间的互操作性成为…

个人主页导航源码

源码简介 个人主页导航源码&#xff0c;个人主页导航源码&#xff0c;一款带后台的个人导航主页源码。 搭建环境 PHP 5.2 Nginx Mysql5.6 安装教程 1.上传源码压缩包到网站目录并解压 2.访问网站域名安装提示进行安装即可 后台路径为&#xff1a;https://域名/admin/ …

ngrok 内网穿透使用

title: ngrok 内网穿透使用 search: 2024-02-29 文章目录 背景Windows安装ngrok指令授权ngrok个人用户Authtoken穿透 http 或 https 服务ngrok的代理http指令ngrok获得静态域名指令ngrok的代理ssh指令 背景 这次寒假回家&#xff0c;很无奈&#xff0c;很多东西放在项目组服务…

3月份 月总结

抓住3月份的尾巴&#xff0c;简单写一篇月度总结。 3月份之所以产出比较少&#xff0c;是因为时间都花在学习和工作上了。 学习的内容包括但不限于 开源Grbl_Esp32 gcode学习 web串口 svg转gcode的生成 字体转svg 位图转矢量图 potrace算法 扫描线相关知识 矢量图编辑器调研 …

Vue2(十一):脚手架配置代理、github案例、插槽

一、脚手架配置代理 1.回顾常用的ajax发送方式&#xff1a; &#xff08;1&#xff09;xhr 比较麻烦&#xff0c;不常用 &#xff08;2&#xff09;jQuery 核心是封装dom操作&#xff0c;所以也不常用 &#xff08;3&#xff09;axios 优势&#xff1a;体积小、是promis…

微软Azure推出9种逼真AI语音服务;OpenAI有限开放Voice Engine访问权限

&#x1f680; 微软Azure推出9种逼真AI语音服务 摘要&#xff1a;微软Azure团队在2023年9月对外宣布&#xff0c;针对商业客户推出了一系列逼真的AI语音服务。最近&#xff0c;该公司进一步表示&#xff0c;这些服务现已包含9种更为真实的人工智能声音&#xff0c;并且已于所有…

PostgreSQL:所有支持的数据类型及建表语句实例

哈喽&#xff0c;大家好&#xff0c;我是木头左&#xff01; 一、引言 在当今这个数据驱动的时代&#xff0c;数据库已经成为了企业和个人不可或缺的工具。而在众多数据库产品中&#xff0c;PostgreSQL以其强大的功能和高度的可扩展性&#xff0c;受到了越来越多开发者的青睐。…

ZC706+AD9361 运行 open WiFi

先到github上下载img&#xff0c;网页链接如下&#xff1a; https://github.com/open-sdr/openwifi?tabreadme-ov-file 用win32 Disk lmager 把文件写入到SD卡中&#xff0c;这一步操作会把SD卡重新清空&#xff0c;注意保存数据。这个软件我会放在最后的网盘链接中 打开linu…

对接中泰极速行情 | DolphinDB XTP 插件使用教程

XTP 是中泰证券推出的高性能交易平台&#xff0c;专为专业投资者提供高速行情及交易系统&#xff0c;旨在提供优质便捷的市场接入通道。目前支持股票、基金、ETF、债券、期权等多个市场&#xff0c;可满足不同投资者需求。 基于 XTP 官方 C SDK&#xff0c;DolphinDB 开发了 X…

【PyTorch Tensor】PyTorch Tensor编程教学:基础与实战

PyTorch是一个开源的机器学习库&#xff0c;它提供了强大的张量计算&#xff08;Tensor computation&#xff09;能力和动态计算图&#xff08;Dynamic computation graph&#xff09;&#xff0c;使得深度学习模型的构建和训练变得更加灵活和直观。在本文中&#xff0c;我们将…

rabbitmq消息处理模式

在 RabbitMQ 中&#xff0c;消费者的消息处理模式可以分为两种&#xff1a;pull 模式和 push 模式⁵。 Pull 模式&#xff1a;消费者主动从消息中间件中拉取消息。这种模式下&#xff0c;每次接收消息都需要拉取一下队列的信息&#xff0c;由于是拉取的&#xff0c;实用性较差&…

使用hping3网络工具构造TCP/IP数据包和进行DDos攻击

1 概述 hping3是一个强大的命令行工具&#xff0c;用于生成、发送和解析TCP/IP协议的数据包。它是开源的网络安全工具&#xff0c;由Salvatore Sanfilippo开发&#xff0c;主要应用于网络审计、安全测试和故障排查等领域。hping3不仅可以作为普通的网络连通性检测工具&#xf…

【蓝桥杯第十三届省赛B】(部分详解)

九进制转十进制 #include <iostream> #include<math.h> using namespace std; int main() {cout << 2*pow(9,3)0*pow(9,2)2*pow(9,1)2*pow(9,0) << endl;return 0; }顺子日期 #include <iostream> using namespace std; int main() {// 请在此…

ROS2从入门到精通1-2:详解ROS2服务通信机制与自定义服务

目录 0 专栏介绍1 服务通信模型2 服务模型实现(C)3 服务模型实现(Python)4 自定义服务5 话题、服务通信的异同 0 专栏介绍 本专栏旨在通过对ROS2的系统学习&#xff0c;掌握ROS2底层基本分布式原理&#xff0c;并具有机器人建模和应用ROS2进行实际项目的开发和调试的工程能力。…

智慧公厕是什么?智慧公厕的主要功能、特点?

智慧公厕&#xff0c;顾名思义&#xff0c;是指应用了智能科技的公共厕所&#xff0c;旨在提供更加便捷、舒适、智能化的卫生服务。相比传统的公厕&#xff0c;智慧公厕不仅拥有更加智能化的设备&#xff0c;还配备了远程监控与管理系统&#xff0c;以及节能环保技术&#xff0…

如何选择优质的外贸网站建设公司?

在当今数字化时代&#xff0c;外贸行业越来越重视在线渠道的发展&#xff0c;而外贸网站建设作为企业对外联系的重要窗口&#xff0c;扮演着至关重要的角色。选择一家优质的外贸网站建设公司&#xff0c;不仅能帮助企业提升品牌形象&#xff0c;还能有效扩大海外市场。那么&…

微信小程序【从入门到精通】——服务器的数据交互

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;开发者-曼亿点 &#x1f468;‍&#x1f4bb; hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍&#x1f4bb; 本文由 曼亿点 原创 &#x1f468;‍&#x1f4bb; 收录于专栏&#xff1a…

OpenCV中的模块:三维显示-VIZ

曾经基于PCL 做过不少点云相关的开发,其中借助VTK进行点云显示。后来基于OpenCV进行三维重建,遇到了点云显示的问题。当时采取的方法是将点云保存下来,然后借助CloudCompare等查看效果。如果能够将VIZ编译进来,预计会提升开发速度。本文章将简要介绍其中Ubuntu和windows下的…

【实战教程】Spring Boot项目集成华为openGauss数据库的关键步骤与注意事项

引言&#xff1a; 随着国产数据库技术的崛起&#xff0c;华为openGauss凭借其高性能、安全可靠及易用性成为了众多开发者的首选方案。本篇技术文章将聚焦于如何在Spring Boot项目中成功集成华为openGauss数据库&#xff0c;并揭示其中的一些关键步骤与注意事项&#xff0c;助您…

Python爬虫之异步爬虫

异步爬虫 一、协程的基本原理 1、案例 案例网站&#xff1a;https://www.httpbin.org/delay/5、这个服务器强制等待了5秒时间才返回响应 测试&#xff1a;用requests写一个遍历程序&#xff0c;遍历100次案例网站&#xff1a; import requests import logging import time…