非独立思考

    class Solution {
        private static HashMap<Integer, Integer> treeMap = new HashMap<>(16);
    
        public TreeNode buildTree(int[] preorder, int[] inorder) {
            // 总体思路:根据先序遍历的根节点,定位到中序遍历的根节点
            // 中序遍历的左端点的下标与根节点的下标之差就是左子树的数量,反之是右子树
            // 每轮递归中,我们都:
            // 1 找到根节点
            // 2 按照数量左子树继续递归,作为当前根节点的left
            // 3 右子树继续递归,作为当前根节点的right
    
            // 记录中序遍历的k-v映射
            for (int i = 0; i < inorder.length; i++) {
                treeMap.put(inorder[i], i);
            }
            TreeNode treeNode = myBuildTree(preorder, inorder,0, preorder.length - 1, 0, inorder.length - 1);
            return treeNode;
        }
    
        /**
         * @param preorder      先序遍历
         * @param inorder       中序遍历
         * @param preOrderLeft  递归中:先序遍历的左端点
         * @param preOrderRight 递归中:先序遍历的右端点
         * @param inOrderLeft   递归中:中序遍历的左端点
         * @param inOrderRight  递归中:中序遍历的右端点
         */
        private TreeNode myBuildTree(int[] preorder, int[] inorder,
                                     int preOrderLeft, int preOrderRight, int inOrderLeft, int inOrderRight) {
            // 定义递归结束条件
            if (preOrderLeft > preOrderRight) {
                return null;
            }
    
            // 递归执行流程
            // 1 找到先序遍历中的根节点,即preOrderLeft
            int preOrderRoot = preOrderLeft;
            // 2 据此定位到中序遍历中的根节点
            int inOrderRoot = treeMap.get(preorder[preOrderRoot]);
            // 3 建立根节点,左递归指向其left,右递归指向其right
            TreeNode root = new TreeNode(preorder[preOrderRoot]);
            // 建立递归的重要参数是他们的参数变量值为多少
            // 根据中序遍历计算左子树个数
            int leftSize = inOrderRoot - inOrderLeft;
            // 递归构造左子树
            // 官方提示:先序遍历中「从 左边界+1 开始的 leftSize」个元素就对应了中序遍历中「从 左边界 开始到 根节点定位-1」的元素
            root.left = myBuildTree(preorder, inorder, preOrderLeft + 1, preOrderLeft + leftSize, inOrderLeft, inOrderRoot - 1);
            // 递归构造右子树
            // 先序遍历中「从 左边界+1+左子树节点数目 开始到 右边界」的元素就对应了中序遍历中「从 根节点定位+1 到 右边界」的元素
            root.right = myBuildTree(preorder, inorder, preOrderLeft + leftSize + 1, preOrderRight, inOrderRoot + 1, inOrderRight);
    
            // 最后返回root
            return root;
        }
    }