大家动手画几遍就会发现,我们的思路是:先在preorder里从左到右选取一个树根,然后在inorder里找到这个树根所在的位置index,然后以index为分界点,再分别处理index左侧的区间和index右侧的区间,当区间里没有元素时,说明这棵子树就画完了,很容易想到用递归实现。
所以实现起来就是不断用两个整型变量left和right夹取inorder中的部分区间,生成各部分子树,全局变量L1标识当前的树根在preorder中的位置,每生成一个树根就++。
此外用引用传参节省空间,用指针(迭代器)遍历节约时间,优化之后效率良好。
代码如下:
class Solution {
private: int L1; //新建了一个成员变量作为全局变量用,用它来标识当前子树的根在preorder中的位置,初始化是0
public:
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
L1 = 0;
TreeNode* root = new TreeNode;
root = create(preorder,inorder,0,inorder.size()-1);
return root;
}
//不断用left和right夹取inorder中的部分区间,生成各部分子树,全局变量L1标识当前树的根节点在preorder中的位置
TreeNode* create(vector<int>& preorder, vector<int>& inorder,int left,int right){ //这里用引用以节省空间
if(left > right) //递归出口,当区间内无元素时说明此节点为空
return nullptr;
TreeNode * node = new TreeNode; //建立当前结点
node->val = preorder[L1++]; //将当前树根的值赋给新建的这个节点,然后L1后移一位
node->left = node->right = nullptr;
//遍历left和right之间的元素,找到根在inorder里的位置
int index = -1;
vector<int>::iterator p = inorder.begin() + left; //定义一个迭代器(其实就是当指针用),指向当前区间首部
for(int i=left; i<=right ; i++){
if(*p == node->val){
index = i; //找到后存在index里,跳出循环
break;
}
else p++; //否则指针前移一位
}
node->left = create(preorder,inorder,left,index-1);
node->right = create(preorder,inorder,index+1,right);
return node;
}
};