分别从中序、后续中组成二叉树(likou106)

likou106本题会给你两个数组,arr1由中序遍历,arr2用后续遍历,返回一个原始二叉树。

首先我们要理解好三种遍历方式的顺序:

(25条消息) 二叉树的理论知识_小肖在路上的博客-CSDN博客

然后再回到这个题:

创建二叉树唯一的方法就是,创建根节点,然后创建左右节点连接上。

所以我们在解题中必须创建根节点,所以就得找到根节点在哪里。 

寻找根节点:

arr2既然是后续遍历,arr2数组的最后一个元素,肯定是一个根节点,并且是最上层的根节点。所以我们每次都是找到arr2的最后一个元素作为根节点。然后递归创建左右节点。

 寻找左右节点:

 arr1是中序遍历,就说明它的根节点左边就是左节点,右边就是右节点。

所以我们每次寻找到根节点后,就可以在arr1中找到该节点的左右节点。

 

package lqb;

import java.util.HashMap;
import java.util.Map;

import shuJuJieGouYuSuanFa.erChaShu.*;

public class likou106 {
    public static void main(String[] args) {
        TreeNode root = new likou106().buildTree(new int[]{9, 3, 15, 20, 7}, new int[]{9, 15, 7, 20, 3});
        f1(root);
    }

    private static void f1(TreeNode root) {
        if (root == null) {
            return;
        }
        System.out.println(root.val);
        f1(root.left);
        f1(root.right);
    }

    Map<Integer, Integer> map = new HashMap<>();

    public TreeNode buildTree(int[] arr1, int[] arr2) {
        for (int i = 0; i < arr1.length; i++) {
            map.put(arr1[i], i);
        }
        return dfs(arr1, 0, arr1.length, arr2, 0, arr2.length);
    }

    private TreeNode dfs(int[] arr1, int arr1Kai, int arr1Lan, int[] arr2, int arr2Kai, int arr2Lan) {
        if (arr1Lan <= arr1Kai || arr2Lan <= arr2Kai) {
            return null;
        }
        int t = map.get(arr2[arr2Lan - 1]);
        TreeNode root = new TreeNode(arr1[t]);
        int indexLen = t - arr1Kai;
        root.left = dfs(arr1, arr1Kai, t, arr2, arr2Kai, arr2Kai + indexLen);
        root.right = dfs(arr1, t + 1, arr1Lan, arr2, arr2Kai + indexLen, arr2Lan - 1);
        return root;
    }
}

既然数组开始下标与结束下标重合,就说明已经没有节点可以使用了。直接返回null,作为所谓的空叶子节点

  if (arr1Lan <= arr1Kai || arr2Lan <= arr2Kai) {
            return null;
        }

然后这里会运用到一个哈希表:

快速寻找某个值的出现个数、位置。

我们要第一时间想到哈希表

既然要在arr1中寻找根节点对应的左右节点。我们就直接将arr1的数据、下标存入map中,快速寻找到下标。 记得将map成员化

 

 for (int i = 0; i < arr1.length; i++) {
            map.put(arr1[i], i);
     }

然后就是寻找根节点:arr2的最后一个数据所对应在arr1的下标,它的左边就是该根节点的左节点,右边就是右节点

 int t = map.get(arr2[arr2Lan - 1]);

现在分别创建根节点:

   TreeNode root = new TreeNode(arr1[t]);
       

然后记录根节点的左节点个数:t为根节点的下标,t的左边所有元素都是左节点,

所以直接【t-arr1开始下标】,因为下一次递归,这一段区间又是一个完整的二叉树,也有左右节点。

 int indexLen = t - arr1Kai;

现在将左右节点赋值:也就是递归求左右节点(求子二叉树)

在这里我们得清楚,递归的参数含义:

 private TreeNode dfs(int[] arr1, int arr1Kai, int arr1Lan, int[] arr2, int arr2Kai, int arr2Lan) 

arr1:中序遍历的数组

arr1Kai:中序遍历数组的开始下标

arr1Lan:中序遍历数组的结束下标。

arr2:后续数组

arr2Kai:后续数组的开始下标。

arr2Lan:后续数组的结束下标。

我也是在写这篇博客的时候才真正理解到,这里为什么要怎么做、

我们通过赋值根节点的左右节点进行递归,就把两个数组分成可四个部分,分别是:

由根节点划分的arr1的左节点,arr1的右节点

再通过根节点的划分,得到arr2的左节点和右节点。

arr1的左节点则是直接【开始节点,t】arr1的右节点【t+1,arr1结束

arr2的左节点是【开始节点,开始节点+t】右节点是【开始节点+t,arr2结束节点

进行左右节点赋值的时候,将四个切割数组传入,达到赋值的目的。

        root.left = dfs(arr1, arr1Kai, t, arr2, arr2Kai, arr2Kai + indexLen);
        root.right = dfs(arr1, t + 1, arr1Lan, arr2, arr2Kai + indexLen, arr2Lan - 1);

 各位一定要仔细思考代码的逻辑,不说了,我再去想半小时。。。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值