挑战 - 每日系列(Algorithm)

83 阅读1分钟

算法小白,2024年2月21日,开始挑战在掘金发布“每日”系列。 (节假日可能会出门所以不算) 涉及到算法,type challenge 等,感兴趣的小伙伴可以持续关注督促互勉 🚀🚀🚀

算法

106. 从中序与后序遍历序列构造二叉树

题意理解

根据二叉树的中序遍历和后序遍历结果,构造出二叉树

思路

  • 二叉树的后序遍历最后一个元素就是二叉树的根节点
  • 二叉树的中序遍历,根节点之前为左子树的中序号遍历结果,根节点之后为右子树的中序遍历结果
  • 同理可得对于后续遍历,根节点索引之前就是左子树的后序遍历,之后为右子树的后续遍历
  • 使用递归,即可找到所有子树的根节点

image.png

解题

const buildTree = (inorder, postorder) => {
  if (!inorder.length) return

  const rootVal = postorder.at(-1)
  const mid = inorder.indexOf(rootVal)
  const root = new ListNode(rootVal)

  root.left = buildTree(inorder.slice(0, mid), postorder.slice(0, mid))
  root.right = buildTree(inorder.slice(mid + 1), postorder.slice(mid, postorder.length - 1))

  return root
}

优化

👆解法存在的问题是,每次递归都会调用 indexOfslice 方法,会造成额外的时间消耗。 可以使用哈希表保存索引和值的对应关系,用位置计算代替 slice

const buildTree = (inorder, postorder) => {
  const indexMap = new Map()
  inorder.forEach((val, index) => indexMap.set(val, index))

  // 用来计算末尾位置的变化
  let length = postorder.length

  const helper = (start, end) => {
    const rootVal = postorder[length--]
    const root = new TreeNode(rootVal)
    const index = indexMap.get(rootVal)

    root.left = helper(start, index - 1)
    root.rigth = helper(index + 1, end)

    return root
  }

  helper(0, inorder.length - 1)
}