题目:
输入某二叉树的前序遍历和中序遍历,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含有重复的数字。
例如,前序遍历序列:{1,2,3,7,3,5,6,8},中序遍历序列:{4,7,2,1,5,3,8,6}
二叉树遍历基本知识:
- 前序遍历:访问根节点,前序遍历左子树,前序遍历右子树
- 中序遍历:中序遍历左子树,访问根节点,中序遍历右子树
- 后序遍历:后序遍历左子树,后序遍历右子树,访问根节点
首先,二叉树编号遵循从上到下、从左到右的顺序,如下图中所示
前序遍历顺序为:{1,2,4,7,3,5,6,8}
中序遍历顺序为:{4,7,2,1,5,3,8,6}
重建原理:
- 由前序遍历可得知根节点为第一位,而在中序遍历中,根节点是隔开左右孩子的,所以根节点的左边为左子树,根节点的右边为右子树;
- 由步骤1得出左子树和右子树的长度,分别得出左右子树的前序遍历和中序遍历;
- 重复步骤1、2,直到左右子树的长度为0,依次返回寻得的根节点。
注意点:明确二叉树的递归特性,明确遍历方法
代码如下:
class Solution {
public:
TreeNode* reConstructBinaryTree(vector<int> pre,vector<int> vin) {
int len = pre.size(); //计算遍历长度
if(len == 0) //长度为0,递归结束
return NULL;
int root_val = pre[0]; //寻找根节点
TreeNode* root = new TreeNode(root_val);
int left_len = 0;
//计算左孩子长度
for(int i=0; i < len ; i++){
if(vin[i] == root_val){
left_len = i;
break;
}
}
vector<int> left_pre, left_vin, right_pre, right_vin;
//将左右子树存入vector,再递归调用重建函数
for(int i = 0; i < left_len; i++){
left_pre.push_back(pre[i+1]);
left_vin.push_back(vin[i]);
}
for(int i = left_len + 1 ; i < len; i++){
right_pre.push_back(pre[i]);
right_vin.push_back(vin[i]);
}
root -> left = reConstructBinaryTree (left_pre, left_vin);
root -> right = reConstructBinaryTree (right_pre, right_vin);
return root;
}
};