题目描述:
输入某二叉树的前序遍历和中序遍历的结果,请重建该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。
例如,给出:
前序遍历 preorder = [3,9,20,15,7]
中序遍历 inorder = [9,3,15,20,7]
返回如下二叉树:
解题思路:
首先考虑先序遍历,先序遍历的顺序是:中->左->右。因此中序数组的第一个数值肯定是二叉树的根节点。再考虑中序遍历,中序遍历的顺序是:左->中->右,因此查找先序遍历第一个数值在中序数组中的位置,如果是在中间,说明先序遍历第一个数字对应的节点有左子树和右子树。在最左边,说明没有左子树,在最右边说明没有右子树。按照这个想法进行递归。
代码如下:
class Solution {
public:
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
TreeNode *p;
if(preorder.empty())return NULL;
buildwholeTree(p,preorder,inorder);
return p;
}
void buildwholeTree(TreeNode* &p,vector<int>& preorder, vector<int>& inorder){
if(preorder.empty())return;
if(inorder.empty())return ;
p = new TreeNode(preorder[0]);
auto it = find(inorder.begin(),inorder.end(),preorder[0]);//it指向的是当前被找到的位置上的下标
int res = it-inorder.begin();//如果preorder[0]在三号位置,这个的结果就是2。
vector<int> left_inorder(inorder.begin(),inorder.begin()+res);//直接构造的时候,res如果是2的话就是这个vector里面只有两个数。也就是重构了找到的值前面的元素
preorder.erase(preorder.begin());
buildwholeTree(p->left,preorder,left_inorder);
inorder.erase(inorder.begin(),inorder.begin()+res+1);
buildwholeTree(p->right,preorder,inorder);
}
};
注:
1、vector本身没有查找函数,没有v.find()查找函数,而像map、unordered_map。有查找m.find()。所以如果是想要查找其中的某一个值就需要使用find函数find(v.begin(),v.end(),x)。
2、当find函数查找到某一个值以后,返回迭代器it,it-v.begin(),表示他们之间差了多少,比如找到那个在第三个位置,res = 2;
3、v.erase和构造函数。想vector v1(v.begin(),v.end()+res)里面只有两个元素。同样erase也只是删除两个元素。