[路飞]_LeetCode_105. 从前序与中序遍历序列构造二叉树

116 阅读2分钟

「这是我参与2022首次更文挑战的第27天,活动详情查看:2022首次更文挑战

题目

给定两个整数数组 preorder 和 inorder ,其中 preorder 是二叉树的先序遍历, inorder 是同一棵树的中序遍历,请构造二叉树并返回其根节点。

示例 1:

image.png

输入: preorder = [3,9,20,15,7], inorder = [9,3,15,20,7]
输出: [3,9,20,null,null,15,7]

示例 2:

输入: preorder = [-1], inorder = [-1]
输出: [-1]

提示:

  • 1 <= preorder.length <= 3000
  • inorder.length == preorder.length
  • -3000 <= preorder[i], inorder[i] <= 3000
  • preorder 和 inorder 均 无重复 元素
  • inorder 均出现在 preorder
  • preorder 保证 为二叉树的前序遍历序列
  • inorder 保证 为二叉树的中序遍历序列

来源:力扣(LeetCode)leetcode-cn.com/problems/co…

解题思路

  • 前序遍历的第一个元素是根节点;
  • 在中序遍历中找到前序遍历的第一个元素
    • 该元素左边是左子树,如下图 inorder 蓝色部分,假设左子树个数是n;
    • 该元素右边是右子树,如下图 inorder 绿色部分;
  • 前序遍历第一个元素后面的n个元素是左子树,如下图 preorder 蓝色部分。后面的是右子树,如下图 inorder 蓝色部分;
  • 将前序遍历的左子树和中序遍历的左子树递归构造成根节点的左子树;
  • 将前序遍历的右子树和中序遍历的右子树递归构造成根节点的右子树;

image.png

代码实现

var buildTree = function (preorder, inorder) {
    //如果前序遍历没有元素则返回空树
    if (preorder.length === 0) return null

    const l_pre = []
    const l_in = []
    const r_pre = []
    const r_in = []

    let pos = 0
    //从中序遍历中找到前序遍历的第一个元素的位置
    while (preorder[0] !== inorder[pos]) pos++

    for (let i = 0; i < pos; i++) {
        //将 preorder 1到pos+1之间的元素加入前序遍历数组
        l_pre.push(preorder[i + 1])
        
        //将 inorder 0到pos之间的元素加入中序遍历数组
        l_in.push(inorder[i])
    }

    for (let i = pos + 1, len = preorder.length; i < len; i++) {
        //将 preorder 的 pos+1到最后的元素加入前序遍历数组
        r_pre.push(preorder[i])
        
        //将 inorder 的 pos+1到最后的元素加入中序遍历数组
        r_in.push(inorder[i])
    }

    const node = new TreeNode(preorder[0])
    //将前序遍历的左半部分和中序遍历的左半部分构造成当前节点的左子树
    node.left = buildTree(l_pre, l_in)
    
    //将前序遍历的右半部分和中序遍历的右半部分构造成当前节点的右子树
    node.right = buildTree(r_pre, r_in)

    return node
};

如有错误欢迎指出,欢迎一起讨论!