主要思路:
前序遍历先访问根节点,然后访问左子树,最后访问右子树;中序遍历先访问左子树,然后访问根节点,最后访问右子树
因此,对于给出的前序遍历,第一个一定是根节点,此时,在中序遍历的结果中找到该根节点,可以将中序遍历的结果分为两部分,这两部分即为左子树和右子树。
假设左子树有k个节点,对于前序遍历来说,对于一个节点,必然是先遍历完其左子树才会遍历右子树,因此前序遍历中第一个节点后紧跟的k个节点一定就是左子树中对应的节点,从第k+1个节点处是其右子树的节点,至此,前序遍历的结果也可以被分为两部分,并且可以分别对应到中序遍历结果的两部分;这两部分即对应根节点的左右子树,因此对这两部分分别进行递归即可得到根节点的左右孩子节点。
KEY:通过中序遍历的结果去确定左右子树的个数,以获取对应子树前序遍历的结果!
class Solution {
public:
unordered_map<int,int> hash; //记录每个val分别对应中序遍历中的第几个位置,方便定位
TreeNode* buildsubTree(vector<int>& preorder,int pos, vector<int>& inorder,int inleft,int inright)
{
if(inleft > inright)
return nullptr;
TreeNode* root=new TreeNode(preorder[pos]);
root->left=buildsubTree(preorder,pos+1,inorder,inleft,hash[preorder[pos]]-1);
root->right=buildsubTree(preorder,pos+1+hash[preorder[pos]]-inleft,inorder,hash[preorder[pos]]+1,inright);
return root;
}
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
for(int i=0;i<inorder.size();i++)
{
hash[inorder[i]]=i;
}
return buildsubTree(preorder,0,inorder,0,inorder.size()-1);
}
};