Leetcode105. 从前序与中序遍历构造二叉树

149 阅读2分钟

要求:

根据一棵树的前序遍历与中序遍历构造二叉树

示例:

前序遍历 preorder = [3,9,20,15,7]
中序遍历 inorder = [9,3,15,20,7]

返回:
    3
   / \
  9  20
    /  \
   15   7

思路:

就拿示例数组来说,前序遍历数组构成为:[根,左子树,右根,右子树],中序遍历的数组为:[左子树,根,右子树]。所以步骤为:

  1. 先得到前序遍历数组的第一个元素,这个元素就是根节点,再去中序遍历的数组中找根节点这个元素,得到其在数组中的索引,以此为分界点,前面是左子树,右边是右子树。自然也能得到左右子树元素的个数。
  2. 根据得到的左右子树的元素个数,再去前序数组里面划定范围,左右子树的范围,由此展开递归。
  3. 左子树的第一个元素也必为左子树的根节点
  4. 右子树的第一个元素也必为右子树的根节点
  5. 得到根节点后再去中序数组里面找根节点的索引,再去划分范围,再这样去递归
  6. 递归终止条件:左边界索引大于右边界索引
  7. 注意:可以先对中序遍历进行Map存储,这样查找元素及索引的时候会很快

代码:

public class TreeNode {
    int val;
    TreeNode left;
    TreeNode right;
    TreeNode(int x) { val = x; }
}

class Solution {
    private Map<Integer, Integer> indexMap;
    public TreeNode buildTree(int[] preorder, int[] inorder) {
        int len = preorder.length;
        indexMap = new HashMap<Integer, Integer>();
        for (int i = 0; i < len; i++) {
            indexMap.put(inorder[i], i);
        }
        return mybuilderTree(preorder, 0, len-1, inorder, 0, len-1);//前序数组中,数组左边界,数组右边界,中序数组中,数组左边界,数组右边界
    }
    public TreeNode mybuildTree(int[] preorder, int left1, int right1, int[] inorder, int left2, int right2) {
        if (left1 > right1) return null;
        if (left2 > right2) return null;
        int root1 = left1;
        int root2 = indexMap.get(preorder[root1]);
        int size = root2 - left2;
        TreeNode root = new TreeNode(preorder[root1]);//先建立根节点
        root.left = mybuildTree(preorder, left1+1, left1+size, inorder, left2, root2-1);
        root.right = mybuildTree(preorder, left1+size+1, right1, inorder, root2+1, right2);
        return root;
    }
}