fe-learning icon indicating copy to clipboard operation
fe-learning copied to clipboard

剑指offer —— 重建二叉树

Open pigpigever opened this issue 5 years ago • 1 comments

点击查看原文 点击查看原题

题目

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

例如,给出

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

返回如下的二叉树:

    3
   / \
  9  20
    /  \
   15   7

解题思路

  • 前序遍历:每次先遍历二叉树的根节点,然后再分别遍历二叉树的左右子树
  • 中序遍历:每次先遍历二叉树的左子树,然后再遍历根节点,最后遍历右子树

结合以上特点,preorder 数组中的第一个值 val 为二叉树的根节点。与之对应的是,我们需要找到 valinorder 数组中的位置 inorderIndex,其中 $[0, inorderIndex - 1]$ 之间的数字分布在左子树,$[inorderIndex + 1, N]$ 之间的数字在右子树;当然,我们还需要找到 preorder 数组中的所有关于左子树的值的分布和所有关于右子树的值的分布,其中 $[1, left + 1]$ 之间的数字分布在左子树,$[right, N]$ 之间的数字分布在右子树。
对于以上推论,我们只要递归的进行下去,这颗树就能被完整的构建出来了。

代码

/**
 * @param {number[]} preorder
 * @param {number[]} inorder
 * @return {TreeNode}
 */
var buildTree = function(preorder, inorder) {
    if (!preorder.length || !inorder.length) {
        return null
    }
    // 根节点的值为 preoder[0]
    const root = new TreeNode(preorder[0])
    // 找到根节点的值在 inorder 中的位置
    // 我们借此来划分 inorder 中分布在左右子树的值
    const inorderIndex = inorder.indexOf(preorder[0])
    // 找到 inorder 中左右子树的边界的值
    // 当然在 preorder 中它们对应左右子树的边界
    // 我们借此来划分 preoder 中分布在左右子树的值
    const left = preorder.indexOf(inorder[inorderIndex - 1])
    const right = preorder.indexOf(inorder[inorderIndex - 1]) + 1
    // 递归构建左右子树
    root.left = buildTree(preorder.slice(1, left + 1), inorder.slice(0, inorderIndex))
    root.right = buildTree(preorder.slice(right), inorder.slice(inorderIndex + 1))
    // 返回结果
    return root
};

pigpigever avatar Apr 27 '20 07:04 pigpigever

上述实现无法通过测试用例,

// 单臂树
[1,2]
[1,2]
-----------
 1
  \
   2

稍微改进一下,

var buildTree = function(preorder, inorder) {
    if(preorder.length === 0 || inorder.length === 0) return null
    const root = new TreeNode(preorder[0])
    const i = inorder.indexOf(preorder[0])
    // 递归构建左右子树
    root.left = buildTree(preorder.slice(1, i + 1), inorder.slice(0, i))
    root.right = buildTree(preorder.slice(i + 1), inorder.slice(i + 1))
    return root
};

metroluffy avatar May 20 '20 02:05 metroluffy