1. Job Roadmap
  2. Home
  3. Problem Set
  4. codenotelist
  5. Forum
  6. course
  7. Shore Share Sessions
  8. Record
  1. Login
  2. Sign Up
  3. Language
    1. English
    2. 한국어
    3. 简体中文
    4. 正體中文
    ZhContent TextSol AI分析

题解:从前序和中序遍历构造二叉树

解题思路

题目给定了二叉树的前序遍历和中序遍历序列,我们需要从这两种遍历序列中恢复出原始的二叉树结构,并最终返回该树的层序遍历结果。

首先,回顾二叉树的前序遍历和中序遍历的特点:

  1. 前序遍历:先访问根节点,再递归访问左子树,最后访问右子树。其顺序为:根 -> 左子树 -> 右子树。

P4064.从前序与中序遍历序列构造二叉树

    1000ms Tried: 1483 Accepted: 525 Difficulty: 5 所属公司 : Hot100
    算法与标签>递归

在线刷题

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

样例1

img

输入

5 5
3 9 20 15 7
9 3 15 20 7

输出

3 9 20 null null 15 7

样例2

输入

1 1
-1
-1

输出

-1

提示

  • 1 <= preorder.length <= 3000
  • inorder.length == preorder.length
  • -3000 <= preorder[i], inorder[i] <= 3000
  • preorder 和 inorder 中都没有重复元素
  • inorder 中每个值都在 preorder 中出现
  • preorder 保证是某棵树的先序序列
  • inorder 保证是同一棵树的中序序列

方法一:递归划分区间(DFS + 哈希表)

构造二叉树的条件是:确定根+确定左子树和右子树。

而:

  1. 先序遍历的第一个元素一定是当前子树的根
  2. 中序遍历里,根左边是左子树,根右边是右子树

如下图所示👇

img

所以我们可以写一个递归函数 dfs(preL, preR, inL, inR),表示:

  • 当前要构建的子树,先序范围是 [preL, preR]
  • 中序范围是 [inL, inR]

每次递归:

  1. 取根:rootVal = preorder[preL]
  2. 在中序inorder里找到rootVal的下标 k
  3. 左子树大小 leftSize = k - inL
  4. 递归构建左子树:
    • 先序:[preL+1, preL+leftSize]
    • 中序:[inL, k-1]
  5. 递归构建右子树:
    • 先序:[preL+leftSize+1, preR]
    • 中序:[k+1, inR]

注意一点:如果每次都在中序数组里线性找 k,会退化成 O(n^2)。
所以我们先用哈希表 idx[val] = 在 inorder 中的位置,这样找根位置就是 O(1)。

代码实现

from collections import deque
from typing import List, Optional


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]:
        n = len(preorder)
        if n == 0:
            return None

        # inorder 值 -> 下标,O(1) 定位根节点
        idx = {v: i for i, v in enumerate(inorder)}

        def dfs(preL: int, preR: int, inL: int, inR: int) -> Optional[TreeNode]:
            # 区间为空,没有节点
            if preL > preR:
                return None

            # 先序区间第一个元素就是当前根
            root_val = preorder[preL]
            root = TreeNode(root_val)

            # 根在中序中的位置
            k = idx[root_val]

            # 左子树节点个数
            left_size = k - inL

            # 构建左子树
            root.left = dfs(
                preL + 1,
                preL + left_size,
                inL,
                k - 1,
            )

            # 构建右子树
            root.right = dfs(
                preL + left_size + 1,
                preR,
                k + 1,
                inR,
            )

            return root

        return dfs(0, n - 1, 0, n - 1)


def serialize_level_order(root: Optional[TreeNode]) -> str:
    if root is None:
        return ""

    q = deque([root])
    out = []
    while q:
        node = q.popleft()
        if node is None:
            out.append("null")
            continue
        out.append(str(node.val))
        q.append(node.left)
        q.append(node.right)

    # 去掉末尾无意义的 null
    while out and out[-1] == "null":
        out.pop()
    return " ".join(out)


def main():
    # ACM 输入格式:
    # 第一行: n m
    # 第二行: preorder 的 n 个数
    # 第三行: inorder 的 m 个数
    n, m = map(int, input().split())
    preorder = list(map(int, input().split()))
    inorder = list(map(int, input().split()))

    root = Solution().buildTree(preorder, inorder)
    print(serialize_level_order(root))


if __name__ == "__main__":
    main()

复杂度分析

  • 时间复杂度:O(n)
    每个节点只会被递归处理一次,哈希表定位根位置是 O(1)。

  • 空间复杂度:O(n)
    哈希表 O(n),递归栈最坏 O(n)(一条链)

面试问答

1. 本题核心思路

递归。还原二叉树的先决条件是:确定根+确定左子树和右子树。考虑先序首元素是根,中序按根一刀切成左右子树,再递归构造左右区间。为了优化复杂度,不在中序里反复找根,用哈希表把“值 -> 下标”先预处理好。

登录后即可使用 AI 分析。

模式
倒计时时长
:

最长 10 小时 59 分;应用后按此时长重新开始。

提示:点击提交记录在左侧题面区域查看详情
题库
AI分析设置
留空使用官方API Key,每天有次数限制(自定义API Key仅限会员和管理员使用,不限次数)
会员和管理员可切换模型;切到 Kimi/智谱/通义/豆包时需填写对应供应商 API Key
升级会员,可将运行与提交冷却时间缩短至 1 秒起

Status

  • Judging Queue
  • Service Status

Development

  • Open Source

Support

  • Help
  • Contact Us

About

  • About
  • Privacy
  • Terms of Service
  • Copyright Complaint
  1. Language
    1. English
    2. 한국어
    3. 简体中文
    4. 正體中文
  2. Legacy mode
  3. Theme
    1. Light
    2. Dark
  1. 京ICP备2025123107号-1
  2. Worker 1, 38ms
  3. Powered by Hydro v5.0.0-beta.18 Community
CLOSE


ScanQRCodePrompt

请使用微信扫描下方二维码完成注册

Forgot password or username?