Leetcode——重建二叉树

题目描述

在这里插入图片描述

题目分析

  • 题目的要求很简单,给你两个数组,分别是前序遍历和中序遍历,要你还原二叉树。
  • 首先我们要明白的是二叉树的前序、中序以及后序遍历的区别以及特点,大家可以自行去网上搜索,相信有很多博主写的文章都能帮助理解。而我个人的理解方法呢,主要从名字入手,前序遍历,就是根节点在前头,然后再左右,就是根-左-右的顺序遍历;中序遍历呢,就是根节点在中间,也就是左-根-右的顺序;而后序遍历呢,就是根节点最后遍历,即左-右-根的顺序来遍历。
  • 从前序遍历和中序遍历的特点,我们可以知道前序遍历第一个必定是根节点,而根节点在中序遍历数组中,又会把它分成左右子树的两个子数组,我们只需要递归着分下去,就可以还原出原本的二叉树。
  • 这道题的思路并不复杂,难的是如何去编码实现。解答中使用一个Map来保存中序数组中每个元素的值以及下标,以此实现在中序数组中快速找到根节点的位置
  • 我们把找到根节点并且分成左右子树这个过程封装成方法并进行递归调用,来实现整棵二叉树的重建。那么何时停止是很重要的问题,递归函数中传入的是两个数组和开始结束的下标,我们可以通过判断下标的值来看看是否已经达到叶子节点的位置。如果开始>结束,说明前序遍历数组中没有值,直接返回root节点。如果开始=结束,说明数组中只有一个值,那么上面已经把它作为该次递归中的根节点,直接退出即可。

题目解答

class Solution {
    public TreeNode buildTree(int[] preorder, int[] inorder) {  
        if(preorder==null || preorder.length == 0)
            return null;
        //map存储每个值及其对应的下标,方便找出每个元素的位置
        Map<Integer,Integer> indexMap=new HashMap<Integer,Integer>();
        int length=preorder.length;
        for(int i=0;i<length;i++){
            indexMap.put(inorder[i],i);
        }
        TreeNode root=buildTree(preorder,0,length-1,inorder,0,length-1,indexMap);
        return root;
    }

    public TreeNode buildTree(int[] preorder,int preorderStart,int preorderEnd
        ,int[] inorder,int inorderStart,int inorderEnd,Map<Integer,Integer> indexMap){
        if(preorderStart>preorderEnd)
            return null;//前序遍历没有值
        int rootVal=preorder[preorderStart];
        //前序第一个必为根结点
        TreeNode root=new TreeNode(rootVal);
        if(preorderStart==preorderEnd){
            //前序数组中只有一个值
            return root;
        }else{
            //获取根结点在中序遍历的位置,此时可以将其分成左右子树的数组
            int rootIndex=indexMap.get(rootVal);
            //保存左右子树节点个数
            int leftNodes=rootIndex-inorderStart,rightNodes=inorderEnd-rootIndex;
            TreeNode leftSubtree=buildTree(preorder,preorderStart+1,preorderStart+leftNodes,inorder,inorderStart,rootIndex-1,indexMap);
            TreeNode rightSubtree=buildTree(preorder,preorderEnd-rightNodes+1,preorderEnd,inorder,rootIndex+1,inorderEnd,indexMap);
            root.left=leftSubtree;
            root.right=rightSubtree;
            return root;
        }
    }
}

新手上路,如果讲的不明白请见谅!如果有什么错误的还请指出,万分感谢!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值