题目描述
输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。
题目分析
给你二叉树的前序遍历数列和中序遍历数列,你可以还原出这个二叉数吗?
——可以!
好的,那就把整个过程逻辑化,然后教机器做出来。
前序遍历序列第一个点就是根节点,中序遍历序列根节点把左子树和右子树分开。利用这个特性,我们在中序遍历序列中找到前序遍历序列的第一个结点的值对应的那个结点,也就是当前树的根节点,(题目说了,每个结点的数都不一样,所以这里不会有歧义。)
那么这个结点左边就是左子树的中序遍历序列,右边就是右子树的中序遍历序列。
注意到,对同一棵树,它的遍历序列在总体上是:前序遍历=根结点+左子树的前序遍历+右子树的前序遍历;中序遍历=左子树的中序遍历+根节点+右子树的中序遍历。利用这个特性,我们就想到用递归来实现。
代码实现
/**
* Definition for binary tree
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
TreeNode* reConstructBinaryTree(vector<int> pre,vector<int> vin) {
//判断这棵树是否为空
if (pre.size() == 0)
return NULL;
//树非空,先建个根结点
TreeNode *result=new TreeNode(pre[0]);
//只有根结点,直接返回
if (pre.size() == 1)
return result;
//还有别的结点
else{
int left_num=0;
//计算中序遍历中根结点的前面有几个结点,这些都是左子树的结点
while(vin[left_num]!=pre[0]) ++left_num;
vector<int> left_pre,left_vin,right_pre,right_vin;
int i;
//创建左子树的前序和中序遍历序列
for(i=0; i<left_num;++i){
left_pre.push_back(pre[i+1]);
left_vin.push_back(vin[i]);
}
//创建右子树的前序和中序遍历序列
for(i=left_num+1;i<pre.size();++i){
right_pre.push_back(pre[i]);
right_vin.push_back(vin[i]);
}
//递归
result->left = reConstructBinaryTree(left_pre,left_vin);
result->right = reConstructBinaryTree(right_pre,right_vin );
return result;
}
}
};
效率展示
用python的话,代码会简洁一些,因为python的库提供了根据数值来划分序列的函数,C++就还得自己写。但是python的运行耗时比较高。从这个比较中我算是更进一步理解了为啥深度学习或者涉及图像处理的程序用python写会方便很多,但时间和硬件成本高。