方法一:dfs
对于一颗子树,前序遍历的第一个点一定是根节点。
然后在中序遍历中找到对应的根节点,左边的点就是左子树,右边是右子树。
然后根据左子树的个数找到右子树在前序遍历对应的根节点 即可。
/**
* 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:
unordered_map<int,int>inid;
TreeNode* bd(int rt,int l,int r,vector<int>& pre, vector<int>&in){
if(l>r)
return nullptr;
TreeNode* ans=new TreeNode(pre[rt]);
int mid = inid[pre[rt]];
ans->left=bd(rt+1,l,mid-1,pre,in);
ans->right=bd(rt+mid-l+1,mid+1,r,pre,in);
return ans;
}
TreeNode* buildTree(vector<int>& pre, vector<int>& in) {
int n=pre.size();
for(int i=0;i<n;i++)inid[in[i]]=i;
return bd(0,0,n-1,pre,in);
}
};
方法二:栈
首先要知道:前序遍历任意两个相邻节点x -> y的关系:
要么是:y是x的左节点。
要么是:y是x或x某个祖宗的右节点。
如果x有左子树,则y一定是x的左节点(根据前序遍历规则。。)
如果x无左子树,有右子树,则y一定是x的右节点。
如果x无左右子树,则y是x某个祖宗的右节点。
上述过程可以用栈模拟。
1.枚举前序遍历的点。把每个点对应的结构体指针压栈
2.判断前一个点(即栈顶)是否含有左右子树(判断中序遍历未访问节点第一个,是否等于栈顶,即可判断其是否有左节点,然后把栈顶弹出,判断下一个中序节点是否等于下一个栈顶,若等于,则说明上一个栈顶无右节点。。)
3.根据判断结果进行构造结构体指针。
/**
* 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:
TreeNode* buildTree(vector<int>& pre, vector<int>& in) {
if(pre.size()==0){
return nullptr;
}
int n=pre.size();
stack<TreeNode*>s;
TreeNode* root;
root=new TreeNode(pre[0]);
s.push(root);
TreeNode *cur;
for(int i=1,j=0;i<n;i++){
if(in[j] != s.top()->val){
s.push(s.top()->left = new TreeNode(pre[i]));
}else{//上一个节点没有左子树
while(!s.empty() && s.top()->val == in[j]){
cur=s.top();
s.pop();
j++;
}
cur->right =new TreeNode(pre[i]);
s.push(cur->right);
}
}
return root;
}
};