解法一
hash map+递归
class Solution {
private:
unordered_map<int,int> index;
public:
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
int n = preorder.size();
for (int i = 0; i < n; i++)
{
index[inorder[i]]=i;
}
return mybuildTree(preorder,inorder,0,n-1,0,n-1);
}
TreeNode* mybuildTree(const vector<int>& preorder,const vector<int>& inorder, int preorder_left, int preorder_right, int inorder_left, int inorder_right){
if(preorder_left>preorder_right) return nullptr;
//前序遍历第一位是根节点位置,用hash map获得中序遍历中根节点的位置
int preorder_root = preorder_left;
int inorder_root = index[preorder[preorder_root]];
//建立根节点
TreeNode* root =new TreeNode(preorder[preorder_root]);
//得到左子树中的节点数
int size_left=inorder_root-inorder_left;
//递归构造左子树,并连接到根节点
root->left=mybuildTree(preorder,inorder,preorder_left+1,preorder_left+size_left,inorder_left,inorder_root-1);
//递归构造右子树
root->right=mybuildTree(preorder,inorder,preorder_left+size_left+1,preorder_right,inorder_root+1,inorder_right);
return root;
}
};
解法二
迭代法,接近双百,但是没怎么看明白
代码中的if块是用前序数组一直构建左子树,如果碰到inorder[inorderIndex],表示到了左下角,这时就需要往上走并处理右子树,也就是while代码块。
class Solution {
public:
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
if(preorder.empty()) return nullptr;
TreeNode* root = new TreeNode(preorder[0]);
stack<TreeNode*> stk;
stk.push(root);
int inorderIndex = 0;
for (int i = 1; i < preorder.size(); i++)
{
int preval = preorder[i];
TreeNode* node = stk.top();
if(node->val!=inorder[inorderIndex]){
node->left=new TreeNode(preval);
stk.push(node->left);
}
else{
while(!stk.empty() && stk.top()->val == inorder[inorderIndex]){
node=stk.top();
stk.pop();
++inorderIndex;
}
node->right=new TreeNode(preval);
stk.push(node->right);
}
}
return root;
}
};
解法三
简单迭代
class Solution {
int index = 0;
public:
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
TreeNode* head;
int left=0;
int right=preorder.size();
head = rebuild(preorder,inorder,left,right);
return head;
}
TreeNode* rebuild(vector<int>& preorder, vector<int>& inorder, int left, int right){
if(index==preorder.size() || left==right) return NULL;
TreeNode* head=NULL;
for (int i = left; i < right; i++)
{
if(preorder[index]==inorder[i]){//找到分界点
head=new TreeNode(preorder[index]);
index++;
//分割左右子树进行递归
head->left=rebuild(preorder,inorder,left,i);
head->right=rebuild(preorder,inorder,i+1,right);
break;
}
}
return head;
}
};