重建二叉树-牛客(Java)

根据给定的前序遍历和中序遍历序列,利用递归方法重建二叉树,要求空间复杂度为O(n),时间复杂度为O(n)。代码实现中,首先检查遍历序列的有效性,然后通过找到根节点在中序遍历中的位置来划分左右子树,并递归地重建它们。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目:重建二叉树

题目描述:

给定节点数为 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;
}

在重建二叉树的递归方法中,最要注意的就是起始和结束位置的下标。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值