输入一棵二叉树前序遍历和中序遍历的结果,请重建该二叉树。
注意:
二叉树中每个节点的值都互不相同;
输入的前序遍历和中序遍历一定合法;
样例
给定:
前序遍历是:[3, 9, 20, 15, 7]
中序遍历是:[9, 3, 15, 20, 7]
返回:[3, 9, 20, null, null, 15, 7, null, null, null, null]
返回的二叉树如下所示:
3
/ \
9 20
/ \
15 7
代码
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
vector<int> preorder,inorder;//因为想在别的方法中使用buildTree的参数,所以把它定义成全局的
map<int,int> m;//因为在中序遍历中查找某个值的下标需要O(n)的复杂度,可以使用hash降为O(1)
TreeNode* buildTree(vector<int>& _preorder, vector<int>& _inorder) {
preorder = _preorder;//将参数赋值为全局变量
inorder = _inorder;
for(int i=0;i< _inorder.size();i++)
m[ _inorder[i]]=i;//将中序遍历的值和下标映射到map中
return dfs(0, _preorder.size()-1,0, _inorder.size()-1);//重建二叉树
}
//pl、pr分别代表前序遍历的起始下标和结束下标
//il、ir分别代表中序遍历的起始下标和结束下标
TreeNode* dfs(int pl,int pr,int il,int ir){
//因为该方法要使用中序遍历的起止下标算左右子树的结点个数,所以该方法需要传入中序遍历的起止下标
if(pl>pr)//前序遍历该区间已无结点
return NULL;
//创建根结点
auto root = new TreeNode(preorder[pl]);//注意点:记得要new
int k=m[root->val];//查找中序遍历中根所在的下标
//构建左子树,前序遍历的根是preorder[pl],所以其左子树的起始下标是pl+1,
//其左子树共有k-il个结点(中序遍历中根左边都是左子树的结点),前序遍历的起始下标为pl+1
//即在pl+1的基础上偏移k-il-1个位置为结束下标(该区间共有k-il个结点),所以pl+1+k-il-1=pl+k-il
//因为中序遍历中根左边都是左子树的结点,所以起止下标分别为il、k-1
root->left = dfs(pl+1,pl+k-il,il,k-1);
//前序遍历中右子树的起始下标为左子树的结束下标+1,
//中序遍历中根右边都是右子树的结点
root->right = dfs(pl+k-il+1,pr,k+1,ir);
return root;//返回以root为根的子树
}
};