根据一棵树的前序遍历与中序遍历构造二叉树。
注意:
你可以假设树中没有重复的元素。
例如,给出
前序遍历 preorder = [3,9,20,15,7]
中序遍历 inorder = [9,3,15,20,7]
返回如下的二叉树:
3
/ \
9 20
/ \
15 7
--------------------------------------------------------------------------------------------------------------
要从图中看出的最重要的一点是前序序列怎末划分成两部分。其实可以先在中序中找出左边有n个元素,然后前序除了第一个头节点之后的n个元素就是左子树上的前序序列。
另外的就是右子树的前序序列。注意上图中前序中序分块的颜色匹配。
class Solution {
public:
vectorpre;
vectorin;
TreeNode* build(int st1, int end1 , int st2 , int end2)
{
if (st1>end1) //判断二叉树是否为空一定要放在最前面,否则下面的new TreeNode(pre[st1])就是错误的语句。
return NULL;
int find;
TreeNode* root=new TreeNode(pre[st1]);
for (int i=st2;i<=end2;i++)
{
if (in[i]==pre[st1])
{
find=i;
break;
}
}
int c=find-st2; //注意前序序列的分法。
root->left=build(st1+1,st1+c,st2,find-1);
root->right=build(st1+c+1,end1,find+1,end2);
return root;
}
TreeNode* buildTree(vector& preorder, vector& inorder) {
pre=preorder;
in=inorder;
return build(0,pre.size()-1,0,in.size()-1);
}
};
前序遍历:负责提供根节点
中序遍历:负责给出左子树有多少个元素,右子树有多少个元素。
小技巧点: 预先把中序遍历中的值对应的索引值用hash表记录下来,之后就方便当前子树的根节点在中序遍历中的哪个位置。
/**
* 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 hash;
TreeNode* dfs(vector& preorder, vector& inorder,int ls,int le,int rs,int re){
if (ls > le) return nullptr;
auto root = new TreeNode(preorder[ls]);
int k = hash[root -> val];
root -> left = dfs(preorder,inorder,ls + 1,ls + k - rs,rs,k - 1); // 左子树有 (k - 1) - rs + 1 = k - rs个元素
root -> right = dfs(preorder,inorder,ls + k - rs + 1,le,k + 1,re);
return root;
}
TreeNode* buildTree(vector& preorder, vector& inorder) {
int n = preorder.size();
int m = inorder.size();
for (int i = 0; i < m; ++i) // 预先把中序遍历中的值对应的索引值用hash表记录下来
hash[inorder[i]] = i;
return dfs(preorder,inorder,0,n - 1,0,m - 1);
}
};