剑指offer编程题《重建二叉树》
题目描述
输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。
思路
我们都知道,通过前序遍历和中序遍历或后序遍历和中序遍历可以唯一确定一棵二叉树。 前序:根、左、右 中序:左、根、右 后序:左、右、根 可以看出,前序的第一个元素是根节点,紧跟着的是左子树序列和右子树序列。而中序的根节点将左右子树分割开来。
因此,就本题而言,可以先从前序序列中找第一个元素,它一定是根节点。然后,在中序中找到该元素(根节点)所在位置,那么该位置左右分别是左子树的中序序列和右子树的中序序列。
在前序序列中,根节点紧跟着左子树、右子树,根据前序左(右)子树节点个数与中序左(右)子树节点个数是一样的,可以在前序序列中分别找到左子树的前序序列和右子树的前序序列。
这样,就有了: 左子树的中序序列—–左子树的前序序列,右子树的中序序列—–右子树的前序序列,这两对序列。 问题又变成了已知前、中序列,求构建子二叉树的问题。很明显,方法已经在上面定义好了,再次调用就好了,这就是用递归的方法逐层求解喽。
C++代码实现:
/**
* 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) {
int size = vin.size();//节点个数
if(size == 0){
return NULL;
}
vector<int> preLeft,preRight,inLeft,inRight;//分别记录前序左字树、前序右字树,中序左子树,中序右子树
int rootValue = pre[0];//前序的第一个元素是根节点值
TreeNode * root = new TreeNode(rootValue);//构建根节点
//在中序序列中找到根节点位置,用i记录
int i = 0;
for(;i<size;i++){
if(vin[i] == rootValue){
break;
}
}
for(int j = 0;j<size;j++){
if(j<i){//左子树
inLeft.push_back(vin[j]);
preLeft.push_back(pre[j+1]);
}else if(j>i){//右子树
inRight.push_back(vin[j]);
preRight.push_back(pre[j]);
}
}
root->left = reConstructBinaryTree(preLeft,inLeft);
root->right = reConstructBinaryTree(preRight,inRight);
return root;
}
};
C++都能实现,其他语言自然不在话下~(≧▽≦)/~啦啦啦