一、题目
二、思路及代码
前序遍历:中、左、右。所以前序遍历的第一个节点是树的根节点,第二个节点是左子树的根节点。。。。
中序遍历:左、中、右。树的根节点在中间某处
我们可以根据二者的特点结合一下:对于前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6}, 根据前序可知1是树的根节点,那么再看中序就可以用1分成左子树{4,7,2}和右子树{5,3,8,6}。再看前序的第二个元素是2,2就是左子树的根节点,于是{4,7}是2的左子树,2没有右子树。 …以此类推就可以得到一颗完整的树。
那么根据上面的分析,我们可以把判断过程分成3步:
- 读取前序的第一个元素,根据这个元素将中序数组拆分成左子树、根节点、右子树;
- 左、右子树各自重复上边的步骤组成自己的二叉树
- 创建一个根节点,左右指针分别指向第二步得到的子树节点
显然每一个节点都可以使用上述步骤,那么我们就可以把这个过程写成递归。
/**
* struct TreeNode {
* int val;
* struct TreeNode *left;
* struct TreeNode *right;
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* };
*/
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param preOrder int整型vector
* @param vinOrder int整型vector
* @return TreeNode类
*/
TreeNode* reConstructBinaryTree(vector<int>& preOrder, vector<int>& vinOrder) {
// write code here
//若数组为空,则说明已经没有新的节点了,返回空
if(vinOrder.size()==0){
return NULL;
}
vector<int> lefttree;
vector<int> righttree;
int i=0;
//获取左子树数组
for(i;i<vinOrder.size();i++){
if(vinOrder[i]==preOrder[0]){
break;
}else{
lefttree.push_back(vinOrder[i]);
}
}
//这里把用过的第一个节点删除掉,那么递归过程就可以一直使用preOrder[0]获取当前根节点
preOrder.erase(preOrder.begin()); //删除掉第一个元素
TreeNode *left=reConstructBinaryTree(preOrder, lefttree);
//获取右子树数组
for(int j=i+1;j<vinOrder.size();j++){
righttree.push_back(vinOrder[j]);
}
TreeNode *right=reConstructBinaryTree(preOrder, righttree);
//当前根节点
TreeNode *root=new TreeNode(vinOrder[i]);
root->left=left;
root->right=right;
return root;
}
};