/**
* struct TreeNode {
* int val;
* struct TreeNode *left;
* struct TreeNode *right;
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* };
*/
class Solution {
private:
unordered_map<int, int> vinIndex; // 中序遍历值到索引的映射
TreeNode* build(vector<int>& preOrder, int preStart, int preEnd,
vector<int>& vinOrder, int vinStart, int vinEnd) {
if (preStart > preEnd || vinStart > vinEnd) {
return nullptr;
}
// 前序遍历第一个节点是根节点
int rootVal = preOrder[preStart];
TreeNode* root = new TreeNode(rootVal);
// 在中序遍历中找到根节点位置
int rootIndex = vinIndex[rootVal];
int leftSize = rootIndex - vinStart; // 左子树节点个数
// 递归构建左右子树
root->left = build(preOrder, preStart + 1, preStart + leftSize,
vinOrder, vinStart, rootIndex - 1);
root->right = build(preOrder, preStart + leftSize + 1, preEnd,
vinOrder, rootIndex + 1, vinEnd);
return root;
}
public:
TreeNode* reConstructBinaryTree(vector<int>& preOrder, vector<int>& vinOrder) {
if (preOrder.empty() || vinOrder.empty() ||
preOrder.size() != vinOrder.size()) {
return nullptr;
}
// 构建中序遍历的索引映射
for (int i = 0; i < vinOrder.size(); i++) {
vinIndex[vinOrder[i]] = i;
}
return build(preOrder, 0, preOrder.size() - 1,
vinOrder, 0, vinOrder.size() - 1);
}
};
算法核心
前序遍历确定根节点:前序遍历的第一个元素就是当前子树的根节点
中序遍历划分左右子树:在中序遍历中找到根节点,左边是左子树,右边是右子树
递归构建:分别对左右子树递归执行上述过程
关键参数说明
preStart, preEnd:当前子树在前序遍历中的范围
vinStart, vinEnd:当前子树在中序遍历中的范围
leftSize:左子树的节点个数,用于确定子树范围
vinIndex:哈希表,存储中序遍历值到索引的映射,加速查找
时间复杂度分析
时间复杂度:O(n)
每个节点只处理一次
哈希表查找根节点位置为 O(1)
空间复杂度:O(n)
递归栈深度为树的高度
哈希表存储 n 个元素的映射