剑指Offer - 07_重建二叉树

该博客介绍了如何根据给定的前序遍历和中序遍历结果来构建二叉树。通过分析二叉树的遍历顺序,可以确定左子树和右子树的边界,并利用递归方法构建整个树结构。示例展示了具体的实现过程,包括创建一个映射存储中序遍历中节点的索引,然后递归地构建左子树和右子树,最终构建完整的二叉树。
摘要由CSDN通过智能技术生成

题目描述

输入某二叉树的前序遍历和中序遍历的结果,请构建该二叉树并返回其根节点。
假设输入的前序遍历和中序遍历的结果中都不含重复的数字。

在这里插入图片描述

  1. 二叉树遍历顺序:

    前序遍历:根节点 -> 左节点 -> 右节点

    中序遍历:左节点 -> 根节点 -> 右节点

  2. 所以二叉树遍历结果可以拆分为:

    前序遍历:[根节点,[左子树遍历结果],[右子树遍历结果]]

    中序遍历:[[左子树遍历结果],根节点,[右子树遍历结果]]

  3. 那么就可以从中序遍历知道左子树和右子树的节点数,也就知道了左子树和右子树在前序遍历中的边界

  4. 从中序遍历中拆分出左子树和右子树,再分别把他们当做一个新的二叉树,找出其根节点位置,依次递归下去

  5. 最后就可以构建出整个二叉树

示例

输入: preorder = [3,9,20,15,7], inorder = [9,3,15,20,7]
输出: [3,9,20,null,null,15,7]

思路

Code

public class Solution {
    //中序遍历每个结点对应的索引
    HashMap<Integer, Integer> indexMap = new HashMap<>();

    public TreeNode buildTree(int[] preorder, int[] inorder) {
        for (int i = 0; i < inorder.length; i++) {
            indexMap.put(inorder[i], i);
        }
        return buildRootNode(preorder, 0, 0, inorder.length - 1);
    }
    
    /**
     * @param preorder 前序遍历
     * @param root     根节点在前序遍历中索引
     * @param left     结点在中序遍历的左边界
     * @param right    结点在中序遍历的右边界
     * @return 根节点
     */
    private TreeNode buildRootNode(int[] preorder, int root, int left, int right) {
        //左边界大于右边界, 递归结束
        if (left > right) {
            return null;
        }
        //根节点值
        int val = preorder[root];
        //创建根节点
        TreeNode rootNode = new TreeNode(val);
        //根节点在中序遍历的索引
        int index = indexMap.get(val);
        //递归左子树
        //根节点索引: 左子树的根节点就在根节点右边, 所以为 root+1
        //左边界: 左边界不变
        //右边界: 中序遍历根节点两边分别为左子树和右子树, 所以左子树的右边界就是根节点左边一个, 即 index-1
        rootNode.left = buildRootNode(preorder, root + 1, left, index - 1);
        //递归右子树
        //根节点索引: 因为前序遍历为 根节点+左子树+右子树, 所以右子树根节点坐标为 根节点坐标+左子树长度+1, 即 root+(index-left)+1
        //左边界: 中序遍历根节点两边分别为左子树和右子树, 所以右子树的左边界就是根节点右边一个, 即 index+1
        //右边界: 右边界不变
        rootNode.right = buildRootNode(preorder, root + index - left + 1, index + 1, right);
        //返回根节点
        return rootNode;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值