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

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

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

难度:中等

1. 题目描述

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

要求:

  • 树中不存在重复元素
  • 数组长度 1 <= n <= 3000
  • -3000 <= preorderi, inorderi <= 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

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 = right
class Solution:
    def buildTree(self, preorder: List[int], inorder: List[int]) -> Optional[TreeNode]:
        def helper(in_start, in_end):
            nonlocal pre_idx
            if in_start > in_end:
                return None
            
            root_val = preorder[pre_idx]
            root = TreeNode(root_val)
            pre_idx += 1
            
            root_in_idx = idx_map[root_val]
            
            root.left = helper(in_start, root_in_idx - 1)
            root.right = helper(root_in_idx + 1, in_end)
            
            return root
        
        n = len(preorder)
        idx_map = {val: i for i, val in enumerate(inorder)}
        pre_idx = 0
        return helper(0, n - 1)

C++

cpp 复制代码
/**
 * 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) {}
 * };
 */
class Solution {
public:
    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
        unordered_map<int, int> idx_map;
        for (int i = 0; i < inorder.size(); ++i) {
            idx_map[inorder[i]] = i;
        }
        int pre_idx = 0;
        return helper(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, int in_start, int in_end) {
        if (in_start > in_end) {
            return nullptr;
        }
        
        int root_val = preorder[pre_idx];
        TreeNode* root = new TreeNode(root_val);
        ++pre_idx;
        
        int root_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);
        
        return root;
    }
};

4. 复杂度分析

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

5. 总结

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

复习

面试经典150题012O(1) 时间插入、删除和获取随机元素(LeetCode 380)

面试经典150题042有效的字母异位词(LeetCode 242)

面试经典150题057链表中是否有环(LeetCode 141)

相关推荐
用户938515635079 小时前
TypeScript 高级类型 + CSS 三列布局:从类型体操到样式工程的进阶之路
css·面试·typescript
Scabbards_11 小时前
面试Leetcode - Heap 堆
java·leetcode·面试
黄敬峰11 小时前
🐳 Docker 从入门到实战:一次搞定容器化 + Nginx 反向代理
面试
程序员清风12 小时前
专业再升级!程序员专属显示器明基RD280UG上手实测!
java·后端·面试
six_13 小时前
C# 上位机(持续更新中)
前端·面试·c#
码匠许师傅14 小时前
【C++ 面试真题】聊聊 C++ 的序列容器
java·c++·面试
ValhallaCoder14 小时前
Leetcode-hot100(2026.08.17)
python·算法·leetcode
东华万里15 小时前
第40篇C++核心基础与工程实践:从底层逻辑到避坑指南
开发语言·c++·面试·大学生专区
wangjialelele18 小时前
动态规划DP经典题型总结(Java、C++):路径、子数组、子序列、背包问题详解
java·c++·算法·面试·动态规划·代理模式
青 春 记 忆18 小时前
LeetCode 104. 二叉树的最大深度|Python 解法详解
python·算法·leetcode