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

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

题目描述

给定两个整数数组 preorderinorder ,其中 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
  • preorderinorder无重复 元素
  • inorder 均出现在 preorder
  • preorder 保证 为二叉树的前序遍历序列
  • inorder 保证 为二叉树的中序遍历序列

思路分析

利用先序(根→左→右)和中序(左→根→右)遍历特性:

  1. 先序首元素为根节点;
  2. 中序中根节点左侧是左子树、右侧是右子树;
  3. 递归拆分左右子树的先序 / 中序区间,构建子树。通过值→索引映射表快速定位根节点在中序的位置,避免遍历,提升效率。

代码实现

cpp 复制代码
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */

// 辅助函数:递归构建二叉树
struct TreeNode* build(int* preorder, int preStart, int preEnd, 
                       int* inorder, int inStart, int inEnd, 
                       int* indexMap) {
    // 递归终止条件:序列为空
    if (preStart > preEnd || inStart > inEnd) {
        return NULL;
    }
    
    // 先序序列第一个元素是根节点
    int rootVal = preorder[preStart];
    struct TreeNode* root = (struct TreeNode*)malloc(sizeof(struct TreeNode));
    root->val = rootVal;
    root->left = NULL;
    root->right = NULL;
    
    // 找到根节点在中序序列中的索引
    int rootIndex = indexMap[rootVal + 3000]; // 偏移3000处理负数
    // 左子树的节点个数
    int leftSize = rootIndex - inStart;
    
    // 递归构建左子树
    root->left = build(preorder, preStart + 1, preStart + leftSize,
                       inorder, inStart, rootIndex - 1, indexMap);
    // 递归构建右子树
    root->right = build(preorder, preStart + leftSize + 1, preEnd,
                        inorder, rootIndex + 1, inEnd, indexMap);
    
    return root;
}

struct TreeNode* buildTree(int* preorder, int preorderSize, int* inorder, int inorderSize) {
    // 构建值到索引的映射表(处理-3000~3000的范围)
    int indexMap[6001] = {0}; // 6001 = 3000 - (-3000) + 1
    for (int i = 0; i < inorderSize; i++) {
        indexMap[inorder[i] + 3000] = i;
    }
    
    // 递归构建二叉树
    return build(preorder, 0, preorderSize - 1, inorder, 0, inorderSize - 1, indexMap);
}

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

题目描述

给定两个整数数组 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 <= inorder.length <= 3000
  • postorder.length == inorder.length
  • -3000 <= inorder[i], postorder[i] <= 3000
  • inorderpostorder 都由 不同 的值组成
  • postorder 中每一个值都在 inorder
  • inorder 保证是树的中序遍历
  • postorder 保证是树的后序遍历

思路分析

利用后序(左→右→根)和中序(左→根→右)遍历特性:

  1. 后序尾元素为根节点;
  2. 中序中根节点左侧是左子树、右侧是右子树;
  3. 递归拆分左右子树的中序 / 后序区间,构建子树。同样用值→索引映射表快速定位根节点,优化查找效率。

代码实现

cpp 复制代码
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */

// 辅助递归函数:构建二叉树
struct TreeNode* build(int* inorder, int inStart, int inEnd,
                       int* postorder, int postStart, int postEnd,
                       int* indexMap) {
    // 递归终止条件:序列无节点
    if (inStart > inEnd || postStart > postEnd) {
        return NULL;
    }
    
    // 后序序列最后一个元素是根节点
    int rootVal = postorder[postEnd];
    struct TreeNode* root = (struct TreeNode*)malloc(sizeof(struct TreeNode));
    root->val = rootVal;
    root->left = NULL;
    root->right = NULL;
    
    // 找到根节点在中序序列中的索引
    int rootIndex = indexMap[rootVal + 3000]; // 偏移3000处理负数
    // 左子树的节点个数
    int leftSize = rootIndex - inStart;
    
    // 递归构建左子树
    root->left = build(inorder, inStart, rootIndex - 1,
                       postorder, postStart, postStart + leftSize - 1,
                       indexMap);
    // 递归构建右子树
    root->right = build(inorder, rootIndex + 1, inEnd,
                        postorder, postStart + leftSize, postEnd - 1,
                        indexMap);
    
    return root;
}

struct TreeNode* buildTree(int* inorder, int inorderSize, int* postorder, int postorderSize) {
    // 构建值到中序索引的映射表(处理-3000~3000的范围)
    int indexMap[6001] = {0}; // 6001 = 3000 - (-3000) + 1
    for (int i = 0; i < inorderSize; i++) {
        indexMap[inorder[i] + 3000] = i;
    }
    
    // 递归构建二叉树
    return build(inorder, 0, inorderSize - 1,
                 postorder, 0, postorderSize - 1,
                 indexMap);
}

总结

两类问题核心逻辑一致:

  1. 从遍历序列中定位根节点(先序首 / 后序尾);
  2. 借助中序拆分左右子树区间;
  3. 递归构建子树,映射表优化根节点查找,时间复杂度 O (n),空间复杂度 O (n)。差异仅在于根节点位置和后序序列的区间拆分规则,核心是利用遍历特性拆分递归区间。
相关推荐
mjhcsp6 分钟前
P14795 [JOI 2026 二次预选] 分班 / Class Division
数据结构·c++·算法
闻缺陷则喜何志丹7 分钟前
【计算几何 最短路 动态规划】P1354 房间最短路问题
数学·算法·动态规划·最短路·计算几何·洛谷
girl-072622 分钟前
2025.12.29实验题目分析总结
数据结构·算法
点云SLAM28 分钟前
Truncated Least Squares(TLS 截断最小二乘)算法原理
算法·slam·位姿估计·数值优化·点云配准·非凸全局优化·截断最小二乘法
sin_hielo37 分钟前
leetcode 840
数据结构·算法·leetcode
feifeigo12338 分钟前
基于MATLAB的木材图像去噪算法实现
算法·计算机视觉·matlab
股朋公式网1 小时前
斩仙飞刀、 通达信飞刀 源码
python·算法
不吃橘子的橘猫1 小时前
NVIDIA DLI 《Build a Deep Research Agent》学习笔记
开发语言·数据库·笔记·python·学习·算法·ai
Xの哲學1 小时前
Linux CFS 调度器深度解析
linux·服务器·算法·架构·边缘计算
bedynamic1 小时前
蚁群算法原理及实现
算法·智能算法