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

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

建树:

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

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

相关推荐
Niuguangshuo1 小时前
论文解读:CTC,端到端序列识别的开山之作
算法·语音识别
找方案2 小时前
AI+人力资源:AI招聘面试的兴起与争议
人工智能·面试·职场和发展
讳疾忌医丶2 小时前
深度拆解 RocksDB 内核:基于 C++17 的 FIFO 调度状态机与温度阶梯自愈设计
java·c++·算法·架构
高亦真2 小时前
今天是学习嵌入式的第37天
linux·学习·算法
罗西的思考4 小时前
[Agent Memory / 强化学习] MemPO源码学习笔记 --- (2)--- 训练
人工智能·算法·机器学习
深圳市方中禾科技5 小时前
FZH1625 LCD 驱动芯片深度评测与实战指南
算法·led
我不会起名字3226 小时前
一天一道算法题(34):回溯法的经典例题(子集)
java·数据结构·python·算法·golang·深度优先·力扣
测试老哥7 小时前
接口测试的测试用例应该怎么写?
自动化测试·软件测试·python·测试工具·职场和发展·测试用例·接口测试
huang5791477 小时前
哈希算法的抗碰撞机制与安全性增强策略4
算法
林浩杨_8 小时前
SIGIR 2026|南京大学:Video-GAR:“通过生成 Query 来验证视频语义理解”的生成增强范式
论文阅读·人工智能·算法