剑指 Offer 07. 重建二叉树

本文介绍了如何根据二叉树的前序遍历和中序遍历来重建二叉树。首先,通过前序遍历获取根节点,然后利用中序遍历找到根节点在中序序列中的索引,从而划分左右子树。通过递归方式,计算左右子树的元素数量,构建左右子树。最后提供了具体的Java代码实现。
摘要由CSDN通过智能技术生成

从中序遍历和前序遍历构建二叉树

链接:剑指 Offer 07. 重建二叉树

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

img

Input: preorder = [3,9,20,15,7], inorder = [9,3,15,20,7]
Output: [3,9,20,null,null,15,7]

示例2:

Input: preorder = [-1], inorder = [-1]
Output: [-1]

限制:

0 <= 节点个数 <= 5000

节点定义如下:

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */

此题与leetcode108. 将有序数组转换为二叉搜索树有所不同,leetcode108. 将有序数组转换为二叉搜索树在我上篇博客可以看到解法,leetcode108. 将有序数组转换为二叉搜索树题中给定线性表建立二叉平衡树,只需二分保持左右子树数目大致相等即可,而此题中左右子树的相对关系要从中序与后序中推得。

前序:根–>左–>右

中序:左–>根–>右

基本思路:先从前序序列中得到根节点的值,由于前序和中序都不含重复元素,因此可以得到此时根节点在中序遍历中的索引(可以想到用HashMap来记录值所在的索引),中序序列中小于索引值的元素成为此时根节点的左子树,而大于索引值的元素就成为右子树,此时,需注意的是:中序得到的左子树的索引范围不对应前序所处的左子树范围,中间需计算左子树的元素数量来决定前序遍历左子树的索引范围。

经过上述分析,可以得到构造二叉树所需的参数了,首先,前序序列preorder、中序序列inorderHashMap(用于记录中序遍历值的索引)、preL(前序起始索引)、preR(前序结束索引)、inL(中序起始索引)、inR(中序结束索引)

代码如下:

public class TreeNode {
      int val;
      TreeNode left;
      TreeNode right;
      TreeNode(int x) { val = x; }
    }

    public TreeNode dfsTree(int[] preorder, int[] inorder, Map<Integer,Integer> hm, int preL, int preR, int inL, int inR){
        if(preL>preR){
            return null;
        }
        int value = preorder[preL];  //前序遍历 首个索引对应的元素即为头节点
        int idx = hm.get(value);	//在中序哈希表中获得头节点在中序中的索引值,用于划分左右子树
        int left_size = idx - inL;	//inL为中序遍历起始索引,left_size来记录左子树元素数量,方便后面递归生成左右子树
        TreeNode root = new TreeNode(value); //创立头节点
        root.left = dfsTree(preorder,inorder,hm,preL+1,preL+left_size,inL,idx-1); //难点在于前序preorder的左子树索引范围,由于根左右的特点,故左子树的范围 =(根节点的索引+1 ,根节点的索引+左子树的大小)
        root.right = dfsTree(preorder,inorder,hm,preL+left_size+1,preR,idx+1,inR);//前序右子树的索引范围 = (根节点的索引+左子树的大小+1,末尾索引)
        return root;
    }

    public TreeNode buildTree(int[] preorder, int[] inorder) {
        Map<Integer,Integer> hm = new HashMap<>();
        for(int i=0;i<inorder.length;i++){
            hm.put(inorder[i],i);
        }
        return dfsTree(preorder,inorder,hm,0,preorder.length-1,0,preorder.length-1);
    }

`

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值