题目6:重建二叉树(leetcode链接:https://leetcode-cn.com/problems/zhong-jian-er-cha-shu-lcof/)
题目分析
在二叉树中,前序序列的第一个节点是根节点,而在中序序列中根节点一般在序列中间位置。中序序列中,根节点值的左侧的m个值是根节点的左子树根节点右侧的n个值值是根节点的右子树,而在前序序列中根节点后面紧跟着的m个值是左子树,其余的n个值是右子树。因此,可以通过递归利用左右子树的前序和中序序列构建左右子树,从而构建二叉树。
例如,下面的二叉树中,前序序列的第一个值就是1。根据中序序列的特点,可以确定中序序列中根节点的左侧有三个值右侧有四个值(左侧的三个值是左子树的值,右侧的四个值是右子树的值)。
由于在中序遍历序列中,有三个值是左子树的节点值,因此左子树总共有三个节点。同样,在前序遍历序列中根节点后面紧跟的3个值就是左子树的前序序列,后边紧跟的所有值就是右子树的前序遍历序列,这样我们就分别找出了左右子树的前序遍历序列和中序遍历序列。
可以通过左右子树的前序㤡和中序序列以同样的方法递归的构建左右子树,而递归的终止条件就是左右子树均为NULL。
代码描述
typedef struct TreeNode TreeNode;
TreeNode* _buildTree(int* preBegin,int* preEnd,int* inBegin,int* inEnd){
//创建节点
TreeNode* root = (TreeNode*)malloc(sizeof(TreeNode));
root->val = preBegin[0];//前序序列的第一个值为根节点
root->left = root->right = NULL;
//如果根节点的左右子树为NULL,返回根节点(前序或者中序序列中只有根节点)
if(preBegin == preEnd){
return root;
}
//在中序序列中找到根节点
int* inRoot = inBegin;
while(*inRoot != preBegin[0]){
inRoot++;
}
//创建左子树
if(inBegin < inRoot)
root->left = _buildTree(preBegin+1,preBegin+(inRoot - inBegin),inBegin,inRoot-1);
//创建右子树
if(inRoot < inEnd){
root->right = _buildTree(preBegin+(inRoot - inBegin)+1,preEnd,inRoot+1,inEnd);
}
return root;
}
struct TreeNode* buildTree(int* preorder, int preorderSize, int* inorder, int inorderSize){
if(preorderSize == 0 && inorderSize == 0){
return NULL;
}
return _buildTree(preorder,preorder+preorderSize-1,inorder,inorder+inorderSize-1);
}