题目链接: leetcode.
已知前序遍历与中序遍历,可以通过前序遍历得到根节点
再通过中序遍历得到左右子树的元素个数,再回到前序划分左右子树
划分得到的左右子树又知道新的前序遍历和中序遍历
所以使用递归
使用map降低查询中序遍历中根节点索引的时间复杂度
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
/*
执行用时:24 ms, 在所有 C++ 提交中击败了87.82%的用户
内存消耗:24.9 MB, 在所有 C++ 提交中击败了94.60%的用户
*/
class Solution {
public:
unordered_map<int, int> M;
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
for(int i = 0;i < inorder.size();i++)
{
M[inorder[i]] = i;
}
//递归参数:前序遍历,中序遍历,当前根节点在前序遍历中的位置,根节点的子树在 *中序遍历* 中的位置范围
return build(preorder, inorder, 0, 0, inorder.size() - 1);
}
TreeNode* build(vector<int>& preorder, vector<int>& inorder, int root, int minn, int maxx)
{
if(minn > maxx)
{
return nullptr;
}
TreeNode* node = new TreeNode(preorder[root]);//太蠢了,这里不能再叫root
int root_index = M[preorder[root]];
//左子树的节点数 = root_index - minn
//左子树的根节点在前序遍历中为 root+1,左子树的范围是 minn到 root_index-1
node -> left = build(preorder, inorder, root + 1, minn, root_index - 1);
//右子树的根节点在前序遍历中的位置为 root + 左子树的节点数 + 1
//右子树的根节点在前序遍历中的位置为 root + root_index - minn + 1
node -> right = build(preorder, inorder, root + root_index - minn + 1, root_index + 1, maxx);
return node;
}
};
参数其实可以不传中序遍历,
执行用时:12 ms, 在所有 C++ 提交中击败了99.68%的用户
内存消耗:24.9 MB, 在所有 C++ 提交中击败了95.10%的用户