leetcode 105从前序和中序遍历序列构造二叉树

复制代码
class Solution {
public:

    // 保存:节点值 -> 中序遍历下标
    // 方便快速找到根节点在中序中的位置
    unordered_map<int,int> index;


    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {

        int n = preorder.size();

        // 建立中序哈希表
        for(int i = 0; i < n; i++){
            index[inorder[i]] = i;
        }

        // 递归构造整棵树
        return build(preorder, inorder,
                     0, n - 1,
                     0, n - 1);
    }


    /*
        pre_left ~ pre_right:
            当前树在前序遍历中的范围

        in_left ~ in_right:
            当前树在中序遍历中的范围
    */
    TreeNode* build(vector<int>& preorder,
                    vector<int>& inorder,
                    int pre_left,
                    int pre_right,
                    int in_left,
                    int in_right){


        // 当前范围没有节点
        if(pre_left > pre_right){
            return nullptr;
        }


        // 前序第一个节点一定是根节点
        int pre_root = pre_left;


        // 找到根节点在中序中的位置
        int in_root = index[preorder[pre_root]];


        // 创建当前根节点
        TreeNode* root = new TreeNode(preorder[pre_root]);


        // 中序中根节点左边就是左子树
        // 计算左子树节点数量
        int left_size = in_root - in_left;


        // 构造左子树
        root->left = build(preorder,
                           inorder,
                           pre_left + 1,
                           pre_left + left_size,
                           in_left,
                           in_root - 1);


        // 构造右子树
        root->right = build(preorder,
                            inorder,
                            pre_left + left_size + 1,
                            pre_right,
                            in_root + 1,
                            in_right);


        // 返回当前子树的根节点
        return root;
    }
};

核心思路总结

这题只需要记住三句话:

1. 前序找根

因为:

复制代码
前序:根 -> 左 -> 右

所以:

复制代码
preorder[pre_left]

就是当前根节点。


2. 中序分左右

因为:

复制代码
中序:左 -> 根 -> 右

找到根的位置:

复制代码
in_root = index[root]

那么:

复制代码
in_root左边 = 左子树
in_root右边 = 右子树

3. 递归构造

当前节点:

复制代码
root = new TreeNode(...)

然后相信递归:

复制代码
root->left = build(...);
root->right = build(...);

返回:

复制代码
return root;

易错点

① 左子树数量

复制代码
int left_size = in_root - in_left;

不是:

复制代码
in_right - in_root

因为这里只求左子树。


② 左子树前序范围

复制代码
pre_left + 1

为什么?

因为:

复制代码
preorder:
根 左 左 左
↑
已经被拿走

所以跳过根。


③ 右子树前序起点

复制代码
pre_left + left_size + 1

因为:

跳过:

复制代码
根节点 + 左子树

④ 递归返回值

一定:

复制代码
return root;

因为父节点需要拿到:

复制代码
root->left = 左子树根
root->right = 右子树根

这题和你刚刚学的 flatten 本质一样:

flatten:

相信递归处理左右子树,我修改当前节点。

建树:

相信递归返回左右子树,我连接当前节点。

你现在学二叉树递归,重点就是抓住这个模式。

相关推荐
一条闲鱼_mytube13 分钟前
分布式 ID 生成方案:雪花算法与号段模式
分布式·算法·wpf
Msir_Modern19 分钟前
Noita 元胞沙盒笔记
算法·unity·c#·游戏引擎·元胞自动机
木井巳1 小时前
【动态规划: 路径问题】不同路径
java·算法·leetcode·动态规划
yuanxi2001 小时前
大众汽车集团或暂停印度电动汽车投资:PSS⁵谈判力视角
职场和发展·创业创新·学习方法
CQU_JIAKE1 小时前
10.25【A】
数据结构·算法
greencherry_2 小时前
大连模屿石膏课模具配比全固定,调色浇注之外还缺什么?
算法·生活
晒太羊的猫2 小时前
hot100子串
java·算法·leetcode
天真小巫3 小时前
2026.10.25总结
职场和发展
小豆庄3 小时前
视频脱敏引擎的追踪难题:转场误判定、ID撞号和淡入窗口
qt·算法·目标检测·音视频·视频·敏捷流程
_张一凡3 小时前
【AIGC面试面经第15期】AI 视频核心基础知识相关问答
面试·职场和发展·aigc