LeetCode题解:105. 从前序与中序遍历序列构造二叉树,递归+数组切割,JavaScript,详细注释

原题连接:https://leetcode-cn.com/problems/construct-binary-tree-from-preorder-and-inorder-traversal/

解题思路:

  1. 参考了多种解法,逐渐优化(补充国外大佬解法)动画演示 105. 从前序与中序遍历序列构造二叉树
  2. 假设有一个二叉树如下:
	      1
	    /   \
	   2     3
	  / \   / \ 
	 4   5 6   7

前序遍历的结果是: [1,2,4,5,3,6,7]
中序遍历的结果是: [4,2,5,1,6,3,7]

  1. 可以将其从根节点1,拆分成两个子树,如下:

左子树:

	   2
	  / \
	 4   5

前序遍历的结果是: [2,4,5]
中序遍历的结果是: [4,2,5]

右子树:

	   3
	  / \ 
	 6   7

前序遍历的结果是: [3,6,7]
中序遍历的结果是: [6,3,7]

  1. 我们可以按照步骤3,将左右子树继续按照根节点继续拆分,可以总结出如下规律:

    • 二叉树的根节点始终在preorder[0]
    • 二叉树可以按照根节点在inorder中的位置rootIndex,将preorderinorder拆分成左右两个子树的结果,如下:

    左子树遍历结果:

    preorder = preorder.slice(1, rootIndex + 1);
    inorder = inorder.slice(0, rootIndex);
    

    右子树遍历结果:

    preorder = preorder.slice(rootIndex + 1);
    inorder = inorder.slice(rootIndex + 1);
    
  2. 经过步骤4的分析,我们可以按照以下逻辑进行递归:

    • 每次递归用preorder[0]的值生成一个根节点。
    • 在通过preorder[0]找到其在inorder中的位置rootIndex,将preorderinorder切割成两部分,分别进行下一层的递归。
    • 将下层递归生成的左右子树,连接到当前根节点上。
    • 递归完成时将当前根节点返回,供上一层递归连接。
    • preorderinorder中的所有值都生成过节点之后,也就完成了整个二叉树的生成。
/**
 * Definition for a binary tree node.
 * function TreeNode(val) {
 *     this.val = val;
 *     this.left = this.right = null;
 * }
 */
/**
 * @param {number[]} preorder
 * @param {number[]} inorder
 * @return {TreeNode}
 */
var buildTree = function (preorder, inorder) {
  // 递归切割数组到最后,数组会为空,此时退出循环
  if (preorder.length === 0) {
    // 数组为空时,表示当前已经无节点需要生成,返回null
    // 让上一层节点的left和right指针指向null
    return null;
  }

  // 使用当前值创建一个节点,即为一个树的根节点
  const root = new TreeNode(preorder[0]);
  // 查找到当前根节点在数组中的位置
  const rootIndex = inorder.findIndex((value) => preorder[0] === value);

  // 将数组对应左子树的部分切割,向下递归
  // 将当前根节点与已生成好的左子树连接
  root.left = buildTree(
    preorder.slice(1, rootIndex + 1),
    inorder.slice(0, rootIndex),
  );
  // 将数组对应右子树的部分切割,向下递归
  // 将当前根节点与已生成好的右子树连接
  root.right = buildTree(
    preorder.slice(rootIndex + 1),
    inorder.slice(rootIndex + 1),
  );

  // 将根节点返回供上层节点连接
  return root;
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值