不能直接用std::vector::at()取根节点索引,因为at()按索引访问,而根在中序中的位置需根据值查找;须用std::find或哈希表定位下标,否则子树切分错位。

为什么不能直接用 std::vector::at() 取根节点索引
因为中序遍历里根节点的位置需要实时查找,而 std::vector::at() 只能按索引取值,不能反向查值。你得用 std::find 或哈希表定位根在中序里的下标——否则递归切分左右子树会错位。
常见错误是写成 inorder[root_val],但 root_val 是节点值,不是索引;C++ 里 vector 不支持用值当索引。
- 正确做法:用
std::find(inorder.begin(), inorder.end(), root_val)得到迭代器,再用std::distance算下标 - 性能敏感时,预处理建
std::unordered_map<int int></int>,键为节点值、值为中序索引,避免每次O(n)查找 - 注意:如果有重复值,这方法失效——题设默认节点值唯一
递归参数怎么传才不越界
前序第一个是根,剩下部分要按中序里左右子树长度来切分。关键不是“数几个”,而是用下标范围精确控制,否则容易 std::out_of_range 或漏节点。
假设中序区间是 [in_left, in_right](闭区间),根在中序下标为 in_root_idx,那么:
立即学习“C++免费学习笔记(深入)”;
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
- 左子树中序长度 =
in_root_idx - in_left - 左子树前序区间 =
[pre_left + 1, pre_left + (in_root_idx - in_left)] - 右子树前序区间 =
[pre_left + (in_root_idx - in_left) + 1, pre_right] - 务必检查
in_left > in_right作为递归终止条件,而不是empty()—— 空 vector 无法反映区间是否有效
构造 TreeNode 时 new 和智能指针怎么选
LeetCode 默认用裸指针,返回 TreeNode*;但本地测试若用 std::unique_ptr,要注意所有权转移和释放时机,否则析构时 double-free。
- 刷题场景:直接
new TreeNode(val),别管内存,平台自动回收 - 工程代码:用
std::make_unique<treenode>(val)</treenode>,但递归返回类型要统一为std::unique_ptr<treenode></treenode>,且所有子树赋值用std::move() - 坑点:混合使用裸指针和智能指针会导致编译失败或未定义行为,比如
root->left = std::move(left_subtree)但root是裸指针
buildTree 函数签名里 vector 是传值还是传引用
必须传 const 引用:const std::vector<int>& preorder</int>。传值会触发深拷贝,时间复杂度从 O(n) 退化成 O(n²),尤其数据量大时超时。
LeetCode 测试用例可能含上千节点,vector 拷贝开销不可忽略。
- 错误写法:
buildTree(std::vector<int> preorder, std::vector<int> inorder)</int></int> - 正确写法:
buildTree(const std::vector<int>& preorder, const std::vector<int>& inorder)</int></int> - 如果加了哈希表缓存中序索引,也建议在函数外预构建并传入,避免每次递归都重复初始化
重建逻辑本身不难,难的是下标计算的边界对齐和容器访问的安全性——多一或少一,整棵树就偏了。

















