[LeetCode] 104. Construct Binary Tree from Preorder and Inorder Traversal

Given two integer arrays preorder and inorder where preorder is the preorder traversal of a binary tree and inorder is the inorder traversal of the same tree, construct and return the binary tree.

Example 1:

Input: preorder = [3,9,20,15,7], inorder = [9,3,15,20,7]
Output: [3,9,20,null,null,15,7]

Example 2:

Input: preorder = [-1], inorder = [-1]
Output: [-1]

Constraints:

  • 1 <= preorder.length <= 3000
  • inorder.length == preorder.length
  • -3000 <= preorder[i], inorder[i] <= 3000
  • preorder and inorder consist of unique values.
  • Each value of inorder also appears in preorder.
  • preorder is guaranteed to be the preorder traversal of the tree.
  • inorder is guaranteed to be the inorder traversal of the tree.

其实这道题要求通过前序遍历数组和中序遍历数组构建一个二叉树, 这里说了数组里没有重复的数字。因为是二叉树,所以想到递归,递归函数constructTree会有7个参数,除了前序遍历数组和中序遍历数组,还要分别加上用到数组部分的边界。即前序遍历数组的左右边界,中序遍历数组的左右边界。最后一个参数是中序遍历数组的位置的index map(主要为了优化查找前序遍历的头节点在中序遍历数组中的位置)。整个函数是O(N)的时间复杂度。
注意要点:

  1. 如何求边界。对于抽象的公示,最好用实际的例子去推导。
  2. 一定要判断左边界是否小于右边界。因为有可能会出现越界的情况,这种情况就是node为空的情况。比如没有一个二叉树没有左子树。前序[9,20,15,7], 中序[9,15,20,7],这个时候headInorderidx = 0,算出的左子树右边界(headInorderidx - 1) 为-1, 但是左子树左边界为0。这种情况就需要返回null,因为说明该node为null。同理右子树为空的时候。
  3. 当两个边界相等的时候,就说明这是leaf,直接返回就行了。
  4. 优化map也可以在递归函数中用loop寻找,但是会浪费时间复杂度。
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public TreeNode buildTree(int[] preorder, int[] inorder) {
        if (preorder == null || inorder == null || preorder.length != inorder.length) {
            return null;
        }
        
        //中序遍历每个值对应的位置记录成一个hashmap
        HashMap<Integer, Integer> inMap = new HashMap<>();
        for (int i = 0; i < inorder.length; i++) {
            inMap.put(inorder[i], i);
        }
        
        return constructTree(preorder, 0, preorder.length - 1, 
                             inorder, 0, inorder.length - 1,
                             inMap);
    }
    
    public TreeNode constructTree(int[] preorder, int preLeft, int preRight,
                                  int[] inorder, int inLeft, int inRight, 
                                  HashMap<Integer, Integer> inMap){
        if (preLeft > preRight || inLeft > inRight) {
            return null;
        }
        if (inLeft == inRight) {
            return new TreeNode(inorder[inLeft]);
        }
        TreeNode head = new TreeNode(preorder[preLeft]);
        int headInorderIdx = inMap.get(preorder[preLeft]);
        head.left = constructTree(preorder, preLeft + 1, preLeft + headInorderIdx - inLeft, 
                                  inorder, inLeft, headInorderIdx - 1, inMap);
        head.right = constructTree(preorder, preLeft + headInorderIdx - inLeft + 1, preRight, 
                                   inorder, headInorderIdx + 1, inRight, inMap);
        return head;
    }
}

posted on 2021-12-29 11:11  codingEskimo  阅读(17)  评论(0编辑  收藏  举报

导航