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:

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

建树:

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

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

相关推荐
weixin_307779134 小时前
C++代码实现MATLAB中的dlarray函数功能
开发语言·c++·算法·matlab
2601_949950638 小时前
练题簿在线免费刷题 从资料整理到考前自测
面试·职场和发展·pdf·word·刷题
hetao17338379 小时前
2026-10-03~04 hetao1733837 的刷题记录
c++·算法
Zootopia62610 小时前
飞行力学知识梳理1|飞行性能与稳定性
人工智能·python·算法·机器学习·无人机·学习方法·信息与通信
longlongzihan10 小时前
从LeetCode 70. 爬楼梯看动态规划:如何精准推导状态转移方程?
c++·算法·leetcode·动态规划
2601_9603563811 小时前
2027校招采购岗解析:数学基础如何迁移到需求预测、成本与供应商分析
人工智能·算法
h_a_o777oah11 小时前
【树论】树链剖分:将树形结构转化为线性结构以处理树上路径问题(洛谷 P3384 附C++代码模板)
数据结构·算法·线段树·acm·树链剖分·树论·重链剖分
HEJOO911 小时前
指针的算术运算详解
java·数据结构·算法
Coder-magician11 小时前
《代码随想录》刷题打卡day47:并查集-part01
数据结构·算法·图论
lsc_blog11 小时前
远程和居家办公的经历,技术简历上怎么摆
面试·职场和发展·重构·pdf·求职招聘