【LeetCode】从前序与中序遍历序列构造二叉树 [M](二叉树重构)

news2024/11/22 14:10:24

105. 从前序与中序遍历序列构造二叉树 - 力扣(LeetCode)

一、题目

给定两个整数数组 preorder 和 inorder ,其中 preorder 是二叉树的先序遍历, inorder 是同一棵树的中序遍历,请构造二叉树并返回其根节点。

示例 1:

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

示例 2:
输入: preorder = [-1], inorder = [-1]
输出: [-1]

提示:

  • 1 <= preorder.length <= 3000
  • inorder.length == preorder.length
  • -3000 <= preorder[i], inorder[i] <= 3000
  • preorder 和 inorder 均 无重复 元素
  • inorder 均出现在 preorder
  • preorder 保证 为二叉树的前序遍历序列
  • inorder 保证 为二叉树的中序遍历序列

二、代码

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    // 优化算法,将原本每一次调用都要遍历一遍找到find的操作,变成总总共只需要遍历一次,存入数组中,以后再去取find直接从数组中就可以获取到,不用便利了,这样整个复杂度变成了O(N)
    public static TreeNode buildTree(int[] pre, int[] in) {
        if (pre == null || in == null || pre.length != in.length) {
            return null;
        }

        // 创建一个Map用来存放中序遍历中每一个值所在的位置
        HashMap<Integer, Integer> valueIndexMap = new HashMap<>();
        for (int i = 0; i < in.length; i++) {
            valueIndexMap.put(in[i], i);
        }

        // 调用递归
        return g(pre, 0, pre.length - 1, in, 0, in.length - 1, valueIndexMap);
    }

    // 有一棵树,先序结果是pre[L1...R1],中序结果是in[L2...R2]
    // 请建出整棵树返回头节点

    // 这个思路就是根据中序根节点左边是其左子树,右边使其右子树,然后前序遍历每一段的最开始节点一定是根节点。通过这个特点来构造出整个二叉树
    // 关键是找到递归出口
    public static TreeNode g(int[] pre, int L1, int R1, int[] in, int L2, int R2,
                             HashMap<Integer, Integer> valueIndexMap) {

        // 这种情况当前节点已经没有左右子节点了,这个时候如果还按照递归的写法L1 + 1,就会导致得到的数已经超过了有边界,这种情况说明遍历到了最底层的空节点,直接返回空
        if (L1 > R1) {
            return null;
        }

        // 递归出口,当先序遍历递归到了只剩下一个节点,说明这个肯定是一个根节点,返回。这里是所有递归返回的开始,从这里开始,这一个分支的递归就不会再向下一层继续了,而是还是向上层返回。因为这个返回位置在继续向下递归调用的方法代码的前面。
        TreeNode head = new TreeNode(pre[L1]);
        if (L1 == R1) {
            return head;
        }

        // 找到当前节点在中序遍历中的位置,用来分割左右子树
        int find = valueIndexMap.get(pre[L1]);
        // 先通过中序遍历获取一下下一层递归所涉及到的数组范围,左子树就是L2~find - 1
        // 这样我们就知道总共涉及到find - 1 - L2个元素,这样先序遍历设计的范围就是,L1+1 ~ L1 + 1 + find - 1 - L2,这样就把这一段子树的左右子节点都涵盖进去了
        head.left = g(pre, L1 + 1, L1 + find - L2, in, L2, find - 1, valueIndexMap);
        // 右子树递归同理
        head.right = g(pre, L1 + find - L2 + 1, R1, in, find + 1, R2, valueIndexMap);

        // 走到这一步直接返回当前根节点,将每一层当前的节点都向上一层返回,这样才这逐层构建出二叉树结构。这一步就是连接每一层递归的接口,用来将下层结果数据传递给上一层,逐层传递,返回到最上层时最终得到结果
        return head;
    }
}

三、解题思路 

通过这道题,我们就知道了递归出口就是当先序遍历的数组只剩下一个的时候,说明已经签不遍历完了,就将这个节点直接返回即可。向下递归的位置就是那两行调用g()方法的方法,这里解释不断地划分左右子树,缩小数据范围。递归节后就是最后的return head,通过这个来讲每一层的递归调用返回给上一层。

每一轮返回的head都是当前层子树的根节点。也就是当前层先序遍历的第一个元素。然后再根据中序遍历找到头节点位置,再将中序遍历头节点左右两边的范围分别向下递归,这样就将剩下的子树再一次划分成左右子树向下递归了。

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

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

相关文章

ASEMI整流桥MB10S,DB207S和ABS210有什么区别

编辑-Z ASEMI整流桥MB10S&#xff0c;DB207S和ABS210有什么区别&#xff1f;这几个型号从外观看都是很相似的&#xff0c;那么他们参数有什么不一样呢&#xff1f; MB10S参数&#xff1a; 型号&#xff1a;MB10S 封装&#xff1a;MBS-4 最大重复峰值反向电压&#xff08;VR…

缓冲区Buffer类的设计(参考Muduo实现)

Buffer的功能需求&#xff1a; Buffer类的设计目的是再创造一层应用层缓冲区。 其对外表现为一块连续的内存(char* p, int len)&#xff0c;以方便客户代码的编写。 size() 可以自动增长&#xf…

Java如何自定义一个变长数组?

文章目录思路分析实现代码测试结果首先需要声明的是&#xff0c; Java本身是提供了变长数组的&#xff0c;即 ArrayList。那么自定义一个变长数组有啥用&#xff1f;其实没啥用或者说用处不大&#xff0c;主要就是为了了解下变长数组的设计理念而已。实际工作中直接使用 ArrayL…

文华财经期货背离信号准确率高指标公式,单边趋势行情增仓上行多空共振策略

由“短线震荡波段王”和“三柱共振-高把握”指标合成 功能 : 1.红绿小波段黄蓝中波段粉青大波段 2.红绿中小波段 3.顶背底背提示 4.金叉死叉提示 5.多和空提示-金叉死叉改写 优点:宽幅震荡和窄幅震荡 弊端:单边行情(可结合多空趋势主图规避) 功能: 1.红绿波段 2.大中量仓-单…

MySQL索引详解

目录 1、为什么要有索引&#xff1f; 2、预备知识 3、为何IO交互要是 Page&#xff1f; 4、如何理解Page以及索引理解 5、索引操作 <1> 创建主键索引 <2> 创建唯一索引 <3> 普通索引的创建 <4> 全文索引的创建 <5> 查询索引 <5>…

Python图像识别实战(五):卷积神经网络CNN模型图像二分类预测结果评价(附源码和实现效果)

前面我介绍了可视化的一些方法以及机器学习在预测方面的应用&#xff0c;分为分类问题&#xff08;预测值是离散型&#xff09;和回归问题&#xff08;预测值是连续型&#xff09;&#xff08;具体见之前的文章&#xff09;。 从本期开始&#xff0c;我将做一个关于图像识别的…

BOOT进程控制模式与故障排错

1. BOOT reboot and shutdown—使用systemctl 命令。 systemctl poweroff–关机 systemctl reboot --重启 systemctl halt 禁用CPU 在7版本中使用systemctl 工具。 选择systemd target graphical.target 桌面图形模式 multi-user.target 多用户模式–命令行 rescue.target 救援…

Linux驱动开发基础__总线设备驱动模型

目录 1 驱动编写的三种方法 1.1 传统写法 1.2 总线设备驱动模型 1.3 设备树 2 在 Linux 中实现“分离”&#xff1a;Bus/Dev/Drv 模型 3 匹配原则 4 函数调用关系 1 驱动编写的三种方法 1.1 传统写法 1.2 总线设备驱动模型 引入platform_device、platform_driver&…

二叉数题型2

目录 二叉搜索树的众数 二叉树的最近公共祖先 修剪二叉树 二叉搜索树的众数 问题描述&#xff1a; 给你一个含重复值的二叉搜索树&#xff08;BST&#xff09;的根节点 root &#xff0c;找出并返回 BST 中的所有 众数&#xff08;即&#xff0c;出现频率最高的元素&#…

PROJ 9.1.1源码下载编译(Win10+VS2022)

目录PROJ什么是PROJPROJ下载方式资源结构编译PROJ打包编译成功的库PROJ 什么是PROJ Proj是一个免费的GIS工具。 它专注于地图投影的表达&#xff0c;以及转换。采用一种非常简单明了的投影表达PROJ&#xff0c;比其它的投影定义简单&#xff0c;但很明显。很容易就能看到各种…

无人机倾斜摄影测量技术的优势有哪些?

传统的地理信息获取工作一般是通过人工测量的方式进行&#xff0c;但这样的测量方式具有工作强度大、成本高等问题。随着现代科技的不断发展&#xff0c;测绘行业对地理信息数据的准确性、时效性要求也越来越高&#xff0c;人工成本和时间成本也为行业带来了巨大的压力。因此&a…

GIT回退到指定版本的两种方法(reset/revert)

实现多人合作程序开发的过程中&#xff0c;我们有时会出现错误提交的情况&#xff0c;此时我们希望能撤销提交操作&#xff0c;让程序回到提交前的样子&#xff0c;本文总结了两种解决方法&#xff1a;reset、revert。 命令特点reset该命令会强行覆盖当前版本和要回退的版本之…

ArcGIS基础实验操作100例--实验15设置字段属性域

本实验专栏来自于汤国安教授《地理信息系统基础实验操作100例》一书 实验平台&#xff1a;ArcGIS 10.6 实验数据&#xff1a;请访问实验1&#xff08;传送门&#xff09; 基础编辑篇--实验15 设置字段属性域 目录 一、实验背景 二、实验数据 三、实验步骤 &#xff08;1&a…

如何用Sonic云真机打王者

使用Sonic进行跨网段部署&#xff0c;助力海外业务的公司进行专项检测。提供定时任务充分利用无人值守时间回归UI测试&#xff0c;省时省力。自研随机事件测试与UI遍历测试&#xff0c;支持打通Jenkins的DevOps流程&#xff0c;Sonic提供图像识别&#xff0c;后续还会添加poco控…

ECS-弹性容器服务 - Part 2

68-ECS-弹性容器服务 - Part 2 Hello大家好&#xff0c;我们今天继续ECS的内容。 Service load balancing 之前的课时讨论过&#xff0c;在ECS集群上创建的ECS服务支持AWS负载均衡器&#xff0c;而应用程序负载均衡器和ECS服务通常是一个很好的搭配&#xff0c;因为应用程序负…

Docker 基础概念介绍

一 什么是 docker &#xff1f; Docker 是一个开源的应用容器引擎&#xff0c;让开发者可以打包他们的应用以及依赖包到一个可移植的镜像中&#xff0c;然后发布到任何流行的 Linux或Windows操作系统的机器上&#xff0c;也可以实现虚拟化。容器是完全使用沙箱机制&#xff0c;…

【nowcoder】笔试强训Day13

目录 一、选择题 二、编程题 2.1参数解析 2.2跳石板 一、选择题 1.一个关系数据库文件中的各条记录 &#xff08;&#xff09; 。 A. 前后顺序不能任意颠倒&#xff0c;一定要按照输入的顺序排列 B. 前后顺序可以任意颠倒&#xff0c;不影响库中的数据关系 C. 前后顺序…

前端面试题之计算机网络篇--HTTP协议

HTTP协议 1. GET和POST的请求的区别 GET和POST方法 GET和POST方法都是HTTP中的方法 什么是 HTTP&#xff1f; 超文本传输协议&#xff08;Hypertext Transfer Protocol&#xff0c;缩写 HTTP&#xff09;旨在启用客户端和服务器之间的通信。 HTTP 充当客户端和服务器之间的…

Android进阶——Javac编译解析

Javac编译器 1.Javac的源码与调试 Javac的源码下载地址&#xff1a;Javac的源码下载地址&#xff0c;在Myeclipse中新建项目Compiler_javac&#xff0c;把源码复制到项目中。 Javac的源码目录&#xff1a; 从Sun Javac的代码来看&#xff0c;编译过程大致可以分为3个过程&…

测试工程师正遭「革命」 AI将改写测试模式

文章目录❤️‍&#x1f525; 软件测试的现状❣️ 功能测试的短板❣️ 过于的依赖工具❤️‍&#x1f525; 测试行业的两极分化❤️‍&#x1f525; 纯功能测试人员应该如何破局❣️ 龙测 AI TestOps 云平台❣️ AI TestOps 亮相 TICA❣️ AI TestOps 所实现的混合模型解决方案…