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

简介: leetcode-105-从前序与中序遍历序列构造二叉树

网络异常,图片无法展示
|


[题目地址][B站地址]


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


示例 1:


网络异常,图片无法展示
|


Input: preorder = [3,9,20,15,7], inorder = [9,3,15,20,7]
Output: [3,9,20,null,null,15,7]
复制代码


示例 2:


Input: preorder = [-1], inorder = [-1]
Output: [-1]
复制代码


提示:


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


本题解题思路如下:


  1. 前序遍历的顺序为根左右,中序遍历的顺序为左根右,所以 preorder[0] 为当前子树根节点的值
  2. 查找该值在 inorder 中的位置,其左边即为左子树中序遍历序列,右边为右子树中序遍历序列
  3. 获取到左右子树中序遍历后,因为子树前序遍历和中序遍历的结果只是顺序不同,但是序列长度是相同的,所以可以根据左子树中序遍历序列长度去 preorder 获取左子树前序遍历序列,剩余部分即为右子树前序遍历序列
  4. 然后就可以通过根节点的值创建根节点,根据左右子树的前序、中序遍历序列递归创建左右子树
  5. 最后返回二叉树的根节点即可


动画演示如下:

网络异常,图片无法展示
|

第一版代码如下:


var buildTree = function(preorder, inorder) {
  // 如果前序遍历序列为空,返回空
  if(preorder.length === 0) return null;
  // 创建子树根节点
  const root = new TreeNode(preorder.shift()),
  // 获取根节点值在中序遍历序列的下标
  ind = inorder.indexOf(root.val);
  // 通过根节点值在中序遍历序列的下标,截取左子树前序遍历,中序遍历序列,创建左子树
  root.left = buildTree(preorder.splice(0,ind),inorder.splice(0,ind));
  // 根据剩余部分截取右子树前序遍历,中序遍历序列,创建右子树
  root.right = buildTree(preorder,inorder.splice(1));
  // 返回根节点
  return root;
};
复制代码


这一版代码提交通过后,只击败了 50% 左右的用户,是因为在递归过过程需要截取左右子树的前序、中序遍历序列,这样的操作增加了执行用时和空间复杂度。


这里我们可以通过维护当前子树前序遍历序列开始结束下标,及中序遍历序列开始结束下标代替截取前序、中序遍历序列的操作,同样达到递归构建左右子树的目的。


优化后代码如下:


var buildTree = function(preorder, inorder) {
  // 传入前序遍历序列开始下标,结束下标,中序遍历序列开始下标
  function build(preStart,preEnd,inStart){
    // 如果前序遍历序列开始下标大于结束下标,说明区间处理完成,返回 null
    if(preStart>preEnd) return null;
    // 通过前序遍历开始下标值构建根节点
    const root = new TreeNode(preorder[preStart]),
    // 获取根节点值在中序遍历序列的下标
    ind = inorder.indexOf(root.val),
    // 获取中序遍历左子树的长度
    leftSize = ind-inStart;
    // 递归的构建左右子树
    root.left = build(preStart+1,preStart+leftSize,inStart);
    root.right = build(preStart+leftSize+1,preEnd,ind+1);
    return root;
  }
  // 返回构建后二叉树的根节点
  return build(0,preorder.length-1,0)
};
复制代码


至此我们就完成了 leetcode-105-从前序与中序遍历序列构造二叉树


如有任何问题或建议,欢迎留言讨论!

相关文章
|
2天前
leetcode代码记录(最长连续递增序列
leetcode代码记录(最长连续递增序列
6 2
|
2天前
leetcode代码记录(最长递增子序列
leetcode代码记录(最长递增子序列
6 1
|
2天前
leetcode代码记录(二叉树的所有路径
leetcode代码记录(二叉树的所有路径
7 0
|
2天前
leetcode代码记录(对称二叉树 中序遍历+回文串 为什么不行
leetcode代码记录(对称二叉树 中序遍历+回文串 为什么不行
6 0
|
2天前
leetcode代码记录(二叉树的最小深度
leetcode代码记录(二叉树的最小深度
6 0
|
2天前
leetcode代码记录(二叉树的最大深度
leetcode代码记录(二叉树的最大深度
5 0
|
2天前
leetcode代码记录(翻转二叉树
leetcode代码记录(翻转二叉树
4 0
|
2天前
|
算法 C++
【刷题】Leetcode 1609.奇偶树
这道题是我目前做过最难的题,虽然没有一遍做出来,但是参考大佬的代码,慢慢啃的感觉的真的很好。刷题继续!!!!!!
6 0
|
2天前
|
算法 索引
【刷题】滑动窗口精通 — Leetcode 30. 串联所有单词的子串 | Leetcode 76. 最小覆盖子串
经过这两道题目的书写,相信大家一定深刻认识到了滑动窗口的使用方法!!! 下面请大家继续刷题吧!!!
7 0

热门文章

最新文章