【LeetCode】重建二叉树day04

时间:2022-07-23
本文章向大家介绍【LeetCode】重建二叉树day04,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

题目

输入某二叉树的前序遍历和中序遍历的结果,请重建该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。

 

例如,给出

前序遍历 preorder = [3,9,20,15,7]
中序遍历 inorder = [9,3,15,20,7]
返回如下的二叉树:

    3
   / 
  9  20
    /  
   15   7
 

限制:

0 <= 节点个数 <= 5000

解题思路

  1. 二叉树的特点是什么?
  • 每个节点最多有两棵子树,所以二叉树中不存在度大于2的节点。也可以没有左子树和右子树。

2.根据便利的特点来进行重建

  • 前序遍历: 二叉树为空,则空操作返回,否则访问根节点,然后前序遍历左子树,再前序遍历右子树。这块就得注意了这就是插入点。
  • 中序便利: 若树为空,则空操作返回,否则从根节点开始,中序遍历根节点的左子树,然后访问根节点,然后访问右子树。

3.通过回想这个两个遍历的特点,那开始重建

4.从中序便利中我们可以判断出根节点是哪一个,那就是前序遍历的preorder[0].

5.我们知道了根节点,哪我们可以根据中续遍历,就可以得出左子树和右子树。有哪些元素。

6.由于树中的节点数量与遍历方式无关,通过中序遍历得知左子树和右子树的节点数量之后,可以根据节点数量得到前序遍历中的左子树和右子树的分界,因此可以进一步得到左子树和右子树各自的前序遍历和中序遍历,可以通过递归的方式,重建左子树和右子树,然后重建整个二叉树。

代码

class Solution {
    public TreeNode buildTree(int[] preorder, int[] inorder) {
    //如果前序遍历数组为空那这棵树也是空的
        if(preorder == null ){
            return null ;
        }else{
        //先拿到中序便利的数量
            int length = inorder.length;
        //通过Map记录中序遍历的值,在后面可以根据根节点拿到左子树和又字树的元素
         Map<Integer,Integer> inorderMap = new HashMap<Integer,Integer>();
            for(int i = 0 ;i<length;i++){
                inorderMap.put(inorder[i],i);
            }
            // 构建一个树根据前序遍历和后续遍历的数组
            //其实有人会问为什么要这样写这么多参数。因为我们要递归调用将其中的遍历的数组切开,然后去便利左子树右子树。
          return  buildTree(preorder,0,length-1,inorder,0,length-1,inorderMap);
        }
    }
      public  TreeNode buildTree(int [] preorder,int preorderStart,int preorderEnd,int[] inorder,int inoderStart, int inorderEnd,Map<Integer,Integer> inorderMap){
        if(preorderStart>preorderEnd){
            return null;
        }
        // 拿到根节点
        int rootVal  = preorder[preorderStart];
        // 创建一颗有根节点的二叉树
        TreeNode root = new TreeNode(rootVal);
        if(preorderStart == preorderEnd){
            return root;
        }else{
        拿到根节点在遍历数组中的位置
            int rootIndex =  inorderMap.get(rootVal);
            // 左子树的节点数量
           int leftNodes =  rootIndex - inoderStart; 右子树节点的数量
           int  rightNodes = inorderEnd - rootIndex;
            构建左子树
            TreeNode leftSubtree = buildTree(preorder, preorderStart + 1, preorderStart + leftNodes, inorder, inoderStart, rootIndex - 1, inorderMap);
            便利右子树
            TreeNode rightSubtree = buildTree(preorder, preorderEnd - rightNodes + 1, preorderEnd, inorder, rootIndex + 1, inorderEnd, inorderMap);
            //将左子树与右子树拼起来
            root.left = leftSubtree;
            root.right = rightSubtree;
        }
        return  root;

    }



}

总结

  1. 刚开始做这道题真的没有思路,于是就看一边答案,然后尝试自己慢慢去写,然后几经调试。就跑出来了。
  2. 核心思想就是中序遍历和前序遍历的算法。
  3. 还有就是理解左子树和右子树的便利过程

参考

  • https://blog.csdn.net/My_Jobs/article/details/43451187
  • https://leetcode-cn.com/problems/zhong-jian-er-cha-shu-lcof/