news 2026/5/1 5:03:01

面试经典150题[072]:从前序与中序遍历序列构造二叉树(LeetCode 105)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
面试经典150题[072]:从前序与中序遍历序列构造二叉树(LeetCode 105)

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

题目链接:从前序与中序遍历序列构造二叉树(LeetCode 105)
难度:中等

1. 题目描述

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

要求:

  • 树中不存在重复元素
  • 数组长度 1 <= n <= 3000
  • -3000 <= preorder[i], inorder[i] <= 3000

示例:

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

2. 问题分析

2.1 规律

  • 先序遍历:根节点 -> 左子树 -> 右子树
  • 中序遍历:左子树 -> 根节点 -> 右子树
  • 先序的第一个元素总是根节点,在中序中找到根节点的位置,可以分割左/右子树。
  • 递归构建:左子树的前序/中序子序列,右子树的前序/中序子序列。
  • 核心问题:如何高效找到中序中根节点的位置,以分割子树?

2.2 贪心思路

我们使用递归 + 哈希表优化:

  • 使用哈希表存储中序遍历的值到索引的映射,便于 O(1) 查找根节点位置。
  • 递归函数:参数为前序/中序的起始/结束索引。
  • 步骤:
    • 如果子树为空(start > end),返回 None。
    • 取前序第一个元素作为根,pre_idx += 1。
    • 在中序中找到根索引 root_in_idx。
    • 递归构建左子树:中序 [in_start, root_in_idx-1],前序相应部分。
    • 递归构建右子树:中序 [root_in_idx+1, in_end],前序相应部分。
  • 全局 pre_idx 跟踪前序位置,避免切片开销。

3. 代码实现

Python

# 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 = rightclassSolution:defbuildTree(self,preorder:List[int],inorder:List[int])->Optional[TreeNode]:defhelper(in_start,in_end):nonlocalpre_idxifin_start>in_end:returnNoneroot_val=preorder[pre_idx]root=TreeNode(root_val)pre_idx+=1root_in_idx=idx_map[root_val]root.left=helper(in_start,root_in_idx-1)root.right=helper(root_in_idx+1,in_end)returnroot n=len(preorder)idx_map={val:ifori,valinenumerate(inorder)}pre_idx=0returnhelper(0,n-1)

C++

/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode() : val(0), left(nullptr), right(nullptr) {} * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} * }; */classSolution{public:TreeNode*buildTree(vector<int>&preorder,vector<int>&inorder){unordered_map<int,int>idx_map;for(inti=0;i<inorder.size();++i){idx_map[inorder[i]]=i;}intpre_idx=0;returnhelper(preorder,inorder,idx_map,pre_idx,0,inorder.size()-1);}private:TreeNode*helper(vector<int>&preorder,vector<int>&inorder,unordered_map<int,int>&idx_map,int&pre_idx,intin_start,intin_end){if(in_start>in_end){returnnullptr;}introot_val=preorder[pre_idx];TreeNode*root=newTreeNode(root_val);++pre_idx;introot_in_idx=idx_map[root_val];root->left=helper(preorder,inorder,idx_map,pre_idx,in_start,root_in_idx-1);root->right=helper(preorder,inorder,idx_map,pre_idx,root_in_idx+1,in_end);returnroot;}};

4. 复杂度分析

  • 时间复杂度:O(n),哈希表构建 O(n),递归遍历每个节点一次
  • 空间复杂度:O(n),哈希表 O(n),递归栈最坏 O(n)

5. 总结

  • 树重建问题+遍历序列→ 递归分割是首选
  • 核心使用哈希表优化索引查找,很通用
    • 类似 BFS 的序列化,但这里是反序列化
    • 可扩展到后序 + 中序的变体

复习

面试经典150题[012]:O(1) 时间插入、删除和获取随机元素(LeetCode 380)
面试经典150题[042]:有效的字母异位词(LeetCode 242)
面试经典150题[057]:链表中是否有环(LeetCode 141)

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/30 9:17:13

Vim光标移动革命:从键盘基准位到高效导航完全指南

Vim光标移动革命&#xff1a;从键盘基准位到高效导航完全指南 【免费下载链接】vim-galore :mortar_board: All things Vim! 项目地址: https://gitcode.com/gh_mirrors/vi/vim-galore Vim作为程序员最爱的文本编辑器&#xff0c;其高效的光标移动能力是核心魅力所在。本…

作者头像 李华
网站建设 2026/5/1 5:00:49

告别频繁 GC:C#.NET PooledList 的设计与使用场景

简介 PooledList<T> 是 高性能集合类型&#xff0c;由 Collections.Pooled 提供&#xff0c;用于替代 List<T>&#xff0c;通过 对象池 (ArrayPool<T>) 复用内部数组来减少 GC&#xff08;垃圾回收&#xff09;压力。 ⚡ 核心目标&#xff1a; 在需要频繁创建…

作者头像 李华
网站建设 2026/4/25 8:55:46

MSBuild BuildCheck终极实战指南:从构建问题到质量保证的高效解决方案

MSBuild BuildCheck终极实战指南&#xff1a;从构建问题到质量保证的高效解决方案 【免费下载链接】msbuild msbuild: 是 .NET Framework 的构建引擎&#xff0c;用于构建和管理 .NET 项目。适合 .NET 开发者和系统管理员使用 msbuild 构建和管理 .NET 项目。 项目地址: http…

作者头像 李华
网站建设 2026/5/1 4:58:52

14、Bison解析器:语法规则、符号处理与多语法处理策略

Bison解析器:语法规则、符号处理与多语法处理策略 1. 递归语法与栈大小控制 在某些情况下,一个包含5000条语句的程序可能会被解析为一个包含10000个元素(语句和分号)的列表。对于大多数Bison解析器来说,处理一个包含10000个元素的右递归列表可能会过大。右递归语法适用于…

作者头像 李华
网站建设 2026/5/1 5:01:38

20、CD刻录与命令行使用全解析

CD刻录与命令行使用全解析 1. CD光盘类型及使用 CD光盘主要有CD - R和CD - RW两种类型,它们在使用上有不同的特点,具体如下表所示: |光盘类型|可擦除|CD - R驱动器录制|CD - R驱动器播放|CD - RW驱动器录制|CD - RW驱动器播放|普通CD播放器播放| | ---- | ---- | ---- |…

作者头像 李华
网站建设 2026/4/21 12:42:56

15、Bison解析器:冲突处理与特殊功能详解

Bison解析器:冲突处理与特殊功能详解 1. 纯解析器与y.output文件 纯解析器在多线程程序中非常有用,每个线程可以解析来自不同源的输入。 Bison可以创建一个日志文件,传统上命名为 y.output ,现在更常见的是 name.output ,它显示解析器中的所有状态以及状态之间的转…

作者头像 李华