Java剑指Offer:4.由前序中序遍历重构二叉树

4.前中序遍历还原二叉树

在这里插入图片描述

思路:

首先要理解如何根据二叉树的前序遍历和中序遍历还原一棵二叉树

具体还原步骤可分为7步,根据下图来讲解具体的实现步骤:

  • 1、先找到前序遍历的第一个节点,也就是根节点root
  • 2、在中序遍历中找到root节点的位置
  • 3、中序遍历中,root节点的没用到的左边节点,为当前root节点的左子树
  • 4、中序遍历中,root节点的没用到的右边节点,为当前root节点的右子树
  • 5、回到前序遍历,根据3步骤中找到的左子树,在前序遍历中画出当前root节点的左子树
  • 6、回到前序遍历,根据4步骤中找到的右子树,在前序遍历中画出当前root节点的右子树
  • 7、继续在root节点的左右子树中找到新的root节点,也就是在划定的范围里的第一个节点,重复以上步骤

在这里插入图片描述

接下来根据上面的理解来解决本题:

本题利用HashMap来存储中序遍历中各个节点的值和下标,键key为节点的值val,值value为节点的下标index

  • 确定根节点root在前序遍历中的位置,得到root的值为1
  • 确定根节点root在中序遍历中的位置,利用map.get(root.val)得到root在中序遍历中的位置为index
  • 接下来就是原理中的3,4,5,6,7步骤的实现

代码实现:

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

public class Solution4 {
    //首先利用HashMap来存储每个中序遍历的key用来存储节点值,value存储下标
    private static Map<Integer,Integer> map = new HashMap<Integer,Integer>();

    public TreeNode reConstructBinaryTree(int[] pre,int[] in) {
        //如果前序遍历长度和中序遍历长度不等,返回null
        if (pre.length != in.length) return null;
        
        //方便找到当前值在中序遍历中的下标
        for (int i = 0; i < in.length; i++) {
            map.put(in[i], i);
        }
        
        //调用辅助函数,重构二叉树
        return help(pre, 0, pre.length - 1, in, 0, in.length - 1);
    }

    /**
     * 
     * @param pre 前序遍历结果集
     * @param preLeft 前序遍历中的当前树的起始位置
     * @param preRight 当前树的结束位置
     * @param in 中序遍历结果集
     * @param inLeft 中序遍历中当前树的起始位置
     * @param inRight 当前树的结束位置
     * @return
     */
    public static TreeNode help(int[] pre, int preLeft, int preRight, int[] in, int inLeft, int inRight) {
        //一定要设置,防止数组下标越界
        if (preLeft > preRight ) {
            return null;
        }
        //构造根节点:前序遍历的第一个节点为根节点
        TreeNode root = new TreeNode(pre[preLeft]);
        
        //找到root节点在中序遍历的位置index
        int index = map.get(root.val);
        
        //根据得到的index,能得到root左右子树的区间,继续递归循环
        root.left = help(pre, preLeft + 1, preLeft + index - inLeft, in, inLeft, index);
        root.right = help(pre, preLeft + index - inLeft + 1, preRight, in, index + 1, inRight);
        return root;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值