LeetCode—剑指Offer:重建二叉树(递归)

重建二叉树(中等)

2020年8月10日

题目来源:力扣
在这里插入图片描述

解题

前序遍历:DLR
中序遍历:LDR

这种题在选择题和填空题非常常见,一般会让你写出后序遍历,那他的规律就有:
前序遍历的第一个点一定是根节点。

如案例,前序遍历第一个点是3,那么根节点一定是3。
在这里插入图片描述
那么找3在中序遍历中的位置,并以它分割成左右子树
在这里插入图片描述
肉眼可以看到左子树只剩9一个节点了,但计算机不知道9是个叶子节点,得用叶子节点的定义告诉它
叶子节点没有子节点,那就是它的子节点都为空
计算机才能知道这是个叶子节点
在这里插入图片描述
看完3的左子树,来看3的右子树
有三个数值15,20,7,这时看前序遍历,哪个数字先出现,哪个就会是根节点,可以直观的看到是20
再在中序遍历中找20的左右子树,那就是15和7了
在这里插入图片描述
知道这个原理后,这道题就很好做了

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    //需要全局的前序遍历的数组
    private int[] preorder;
    //使用HashMap记录中序遍历,key为具体值,value为索引
    private Map<Integer,Integer> inorder_map=new HashMap<>();
    public TreeNode buildTree(int[] preorder, int[] inorder) {
        //前序遍历赋值到全局数组中
        this.preorder=preorder;
        int len=inorder.length;
        for(int i=0;i<len;i++){
            inorder_map.put(inorder[i],i);
        }
        //调用递归方法,把最大的子树范围传进去
        return recur(0,0,len-1);
    }
    //构建递归方法,参数分别为前序遍历确立的根,子树的左边界,子树的右边界
    private TreeNode recur(int root,int left_root,int right_root){
        //如果左边界的值大于右边界,返回null
        if(left_root>right_root)
            return null;

        //构建新的TreeNode
        TreeNode node=new TreeNode(preorder[root]);
        
        //根据前序遍历的数组取出根节点的值,按这个值查找在中序遍历数组的位置,以便于划分左右子树
        int inorder_root_index=inorder_map.get(preorder[root]);

        //取当前节点的左子树范围,调用递归。
        //参数:前序遍历的下一个数,就会是下一个根节点;左边界不变,右边界为上个根节点的左一位
        node.left=recur(root+1,left_root,inorder_root_index-1);

        //取当前节点的右子树范围,调用递归
        //参数:当前的根节点,加上左子树的数量,再加一就会是下一个根节点;左边界为上个根节点的后一位,右边界不变
        //左子树的数量为:当前根节点在中序遍历的索引,减去中序遍历的左边界
        node.right=recur(root+inorder_root_index-left_root+1,inorder_root_index+1,right_root);

        return node;
    }
}

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_41541562/article/details/107905313