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

221 阅读2分钟

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

题目

给定一棵树的前序遍历 preorder 与中序遍历  inorder。请构造二叉树并返回其根节点。

示例1

image.png

Input: preorder = [3,9,20,15,7], inorder = [9,3,15,20,7]
Output: [3,9,20,null,null,15,7]

解题思路

按照人遇到前序遍历和中序遍历的数组构建二叉树;

已知:
前序遍历[根节点,左节点,右节点]
中序遍历[左节点,根节点,右节点]

前序遍历的第一个值是根节点,根据前序遍历第一个值,在中序遍历中找到该值位置;该位置左侧为左节点数据,右侧为右节点数据。 这个不难理解吧

比如:

Input: preorder = [3,9,20,15,7], inorder = [9,3,15,20,7]

  • 前序第一个值是3;
  • 3在中序遍历中下标为1,inorder左侧元素有[9],inorder右侧元素有[15,20,7] 下一步怎么处理呢?

看到这里就应该想到递归了;

递归需要找条件呀,什么条件?

根节点左侧节点的前序遍历数组和中序遍历数组;

现在知道根节点左侧节点中序数组为[9],还需要知道根节点左侧节点前序数组

观察这个已知条件:
前序遍历[根节点,左节点,右节点]
中序遍历[左节点,根节点,右节点] 前序遍历,中序遍历中右节点位置是不变的,那是不是说在前序遍历,中序遍历中根节点+左节点的数量是一致的?

在本例中,第一个元素3的下标是1;表示根节点到左节点有1个元素;

那么根节点的左侧节点前序遍历是不是根据preorder计算从0开始到1结束呀;又因为根节点是0,所有根节点的右侧节点前序遍历数组为[9];

同理:根节点的右侧节点中序遍历数组为[15,20,7],前序遍历数组为[20,15,7];

提示:下一节点的前序遍历数组找当前节点前序遍历数组划分,下一节点的中序遍历数组找当前节点中序遍历数组划分

根据上述思路编辑代码如下

代码

var buildTree = function (preorder, inorder) {
  if (preorder.length === 0 || inorder.length === 0) return null;
  const root = new TreeNode(preorder[0]);
  for (let i = 0; i < preorder.length; i++) {
    if (preorder[0] === inorder[i]) {
      let pre_left = preorder.slice(1, i + 1);
      let pre_right = preorder.slice(i + 1, preorder.length);
      let in_left = inorder.slice(0, i);
      let in_right = inorder.slice(i + 1, inorder.length);
      root.left = buildTree(pre_left, in_left);
      root.right = buildTree(pre_right, in_right);
      break;
    }
  }
  return root;
};