剑指 Offer 07. 重建二叉树

该博客介绍了如何通过先序和中序遍历的数组来构建二叉树。首先,利用先序遍历找到中序遍历中根节点的位置,然后划分左右子树的区间。接着,递归地构建左子树和右子树,直到遍历到叶子节点。整个过程利用了哈希映射存储中序遍历的索引,以便快速查找。

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

整体思想为:

先通过先序找到中序中root的位置,
再通过中序root的位置找到左子树的区间,和右子树的区间
递归左右子树
当穿过叶子结点结束

在这里插入图片描述

public class Offer07 {
    /** 先通过先序找到中序中root的位置,
     * 再通过中序root的位置找到左子树的区间,和右子树的区间
     * 递归左右子树
     *
     * 当穿过叶子结点结束
     * */

    private HashMap<Integer,Integer> map;
    private int[] preorder;

    public TreeNode buildTree(int[] preorder, int[] inorder) {
        /** 将中序遍历的数组存入map中,方便根据结点的值查找到对应索引*/
        this.map = new HashMap<Integer, Integer>();
        int idx = 0;
        for (int i :
                inorder) {
            map.put(i, idx++);
        }
        this.preorder = preorder;

        /** 调用递归*/
        return helper(0,0,preorder.length-1);

    }
    /** 创建执行递归的函数  传入先序的root结点的索引,和中序的区间的左右边界索引  返回子树*/
    public TreeNode helper(int pre_root_idx, int in_left_idx, int in_right_idx){
        /** 终止条件: 区间大小为0*/
        if (in_left_idx > in_right_idx) return null;

        /** 问题与子问题之间的关系为:
         *         root.left = helper(先序的左子树root结点的索引,中序左子树的区间索引,当前结点)
         *         root.right = helper(先序的右子树root结点的索引,中序右子树的区间索引,当前结点)
         *         return root;*/
        TreeNode root = new TreeNode(preorder[pre_root_idx]);//建根节点,也就是先序遍历的第一个元素

        //     左子树           先序root结点索引+1      中序left         中序root结点的索引-1
        root.left = helper(pre_root_idx+1,in_left_idx,map.get(preorder[pre_root_idx])-1);
        //     右子树           先序root结点+左子树的长度                                                                中序root结点+1                       中序右边界
        root.right = helper(pre_root_idx + (map.get(preorder[pre_root_idx]) - in_left_idx + 1),map.get(preorder[pre_root_idx])+1,in_right_idx);
        return root;
    }

}
class TreeNode {
    int val;
    TreeNode left;
    TreeNode right;
    TreeNode(int x) { val = x; }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值