题目:重建二叉树
题目描述:
给定节点数为 n 的二叉树的前序遍历和中序遍历结果,请重建出该二叉树并返回它的头结点。
例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建出如下图所示。
提示:
1.vin.length == pre.length
2.pre 和 vin 均无重复元素
3.vin出现的元素均出现在 pre里
4.只需要返回根结点,系统会自动输出整颗树做答案对比
数据范围:n≤2000,节点的值 −10000≤val≤10000
要求:空间复杂度 O(n),时间复杂度 O(n)
示例1:
输入:[1,2,4,7,3,5,6,8],[4,7,2,1,5,3,8,6]
返回值:{1,2,3,4,#,5,6,#,7,#,#,#,8}
示例2:
输入:[1],[1]
返回值:{1}
示例3:
输入:[1,2,3,4,5,6,7],[3,2,4,1,6,5,7]
返回值:{1,2,5,3,4,6,7}
二叉树的节点类:
class TreeNode{
int val;
TreeNode left;
TreeNode right;
public TreeNode(int x){
val = x;
}
}
基本思想:
如图中所述,我们使用递归的方法来进行二叉树的重建
代码实现:
public TreeNode reConstructBinaryTree(int [] pre,int [] vin) {
// 如果前序遍历和中序遍历的长度不一样,说明这肯定不能构成一个二叉树,
// 或者前序遍历或者中序遍历有一个为 null 那也不能构成一个二叉树
if(pre.length != vin.length || pre == null || vin == null){
return null;
}
return reConstructBinaryTreeHelper(pre,0,pre.length - 1,vin,0,vin.length - 1);
}
// 实现一个函数用来重建二叉树
public TreeNode reConstructBinaryTreeHelper(int[] pre,int preStart,int preEnd,int[] vin,int
vinStart,int vinEnd){
// 如果前序遍历的起始位置大于结束位置,或者中序遍历的起始位置大于结束位置,那么就返回 null
if(preStart > preEnd || vinStart > vinEnd){
return null;
}
// 创建一个新节点,这个节点的值就是前序遍历的第一个元素,也就是当前二叉数的根节点
TreeNode root = new TreeNode(pre[preStart]);
for(int i = vinStart;i <= vinEnd;i++){
if(pre[preStart] == vin[i]){ // 说明在中序中找到了根节点的位置
// 在中序遍历中找到了根节点,那么就要对其左子树和右子树进行重建了
// 对于左子树,
// 前序遍历的起始位置为 根节点 + 1 , 也就是preStart + 1,
// 结束位置为起始位置 + 左子树的个数,即preStart + 1 + i - vinStart - 1
// 中序遍历的起始位置为 vinStart
// 结束位置为 根节点的前一个位置 ,即 i- 1
root.left = reConstructBinaryTreeHelper(pre,preStart + 1,preStart + i -
vinStart,vin,vinStart,i - 1);
// 对于右子树,
// 前序遍历的起始位置为 根节点 +左子树的节点个数,即 preStart + i - vinStart + 1
// 结束位置为 preEnd
// 中序遍历的起始位置为 根节点的后一个节点,即 i + 1
// 结束位置为 vinEnd
root.right = reConstructBinaryTreeHelper(pre,preStart + i - vinStart +
1,preEnd,vin,i + 1,vinEnd);
break;
}
}
return root;
}
在重建二叉树的递归方法中,最要注意的就是起始和结束位置的下标。