leetcode【105/106/108/109】由xxx(遍历序列/数组/链表...)生成xxx二叉树 类型总结 [js解法]

本文总结了LeetCode中由数组、链表等生成二叉树的题目,包括105、106、108、109题。解题思路涉及找到根节点、递归构造左右子树,并过滤无节点或单节点的情况。对于数组,通过前序和中序或中序和后序确定根节点;对于有序数组和链表,转化为二叉搜索树,注意保持高度平衡。文章提供了JavaScript实现的代码示例。
摘要由CSDN通过智能技术生成

最近写的leetcode的100多题位置的时候,出现了几题由xxx(数组/链表/…)生成树的一类型的题,总结一下

用xx(数组/链表/…)生成树的题:

  1. 再去找这个树的根节点并生成一个基础的TreeNode
  2. 再通过递归解决左右节点,逐渐拼接上去
  3. 同时要把无结点和只有一个节点的过滤出去

先看105,106由前序+中序/中序+后序生成二叉树

同样是先找到二叉树的根节点

  • 前序+中序

    1. 整棵树根节点为前序数组的第一个数,根据这个根节点new TreeNode()
    2. 然后就可以根据这个节点在前序和中序数组中找到根节点的左右子树数组,之后递归
    3. 同时在函数的最前面将无节点和只有一个节点的两种情况过滤出去

    所以代码为

    var buildTree = function (preorder, inorder) {
      if (preorder.length === 0) {
        return null;
      }
      if (preorder.length === 1) {
        return new TreeNode(preorder[0]);
      }
      const root = preorder[0]; // 拿到根节点
      const index = inorder.indexOf(root); // 找到根节点在中序数组中的位置
      const inLeft = inorder.slice(0, index); // 根据位置拿到前序中序数组中的左右子树
      const inRight = inorder.slice(index + 1);
      const preLeft = preorder.slice(1, index + 1);
      const preRight = preorder.slice(index + 1);
      const node = new TreeNode(root);
      node.left = buildTree(preLeft, inLeft); // 递归
      node.right = buildTree(preRight, inRight);
      return node;
    };
    
  • 同样中序加后序也是一样的思路,但是取出子树时的做法和前序+中序有点点不一样,这里涉及的是二叉树的知识了,直接上代码

    var buildTree = function (inorder, postorder) {
      if (inorder.length === 0) {
        return null;
      }
      if (inorder.length === 1) {
        return new TreeNode(inorder[0]);
      }
      const root = postorder[postorder.length - 1];
      const index = inorder.indexOf(root);
      const postLeft = postorder.slice(0, index);
      const postRight = postorder.slice(index, postorder.length - 1);
      const inLeft = inorder.slice(0, index);
      const inRight = inorder.slice(index + 1);
      const node = new TreeNode(root);
      node.left = buildTree(inLeft, postLeft);
      node.right = buildTree(inRight, postRight);
      return node;
    };
    

再看108和109,分别是将有序数组/有序链表转换成二叉搜索树,需要注意的是这里的二叉搜索树指的是 高度平衡二叉搜索树—— 一个高度平衡二叉树是指一个二叉树每个节点的左右两个子树的高度差的绝对值不超过 1

  • 数组的比较好处理,因为需要左右子树高度差绝对值不超过1,所以直接找到传入的有序数组中间的那个数作为根节点,将由根节点切割生成的左右数组作为左右子树进行遍历,依旧需要对两种情况进行过滤

    var sortedArrayToBST = function (nums) {
      if (nums.length === 0) {
        return null;
      }
      if (nums.length === 1) {
        return new TreeNode(nums[0]);
      }
      let mid = parseInt(nums.length / 2); // 获得根节点的索引
      let root = new TreeNode(nums[mid]);
      root.left = sortedArrayToBST(nums.slice(0, mid));
      root.right = sortedArrayToBST(nums.slice(mid + 1));
      return root;
    };
    
  • 链表的复杂一些,因为它不能直接像数组那样直接取出根节点,所以需要设置两个指针,通过前面的指针每次走两次,后面的指针每次走一次,来获得中间的那个数以生成根节点

    (此题参考博客:https://blog.csdn.net/weixin_36769175/article/details/81332038)

    同时因为链表不能像数组那样直接slice来获得左右子树的数组,所以需要设多一个索引位来作为尾部位置的索引,头部的就使用参数中给的head

    所以递归的时候写多一个函数作为传入两个参数:headtail的递归

    var childSort = function (head, tail) {
      if (head === tail) {
        return null;
      } else if (head.next === tail) {
        return new TreeNode(head.val);
      } else {
        let front = head;
        let end = head;
        while (front !== tail && front.next !== tail) {
          front = front.next.next;
          end = end.next;
        } // 此时的end即为中间位置的节点
        var node = new TreeNode(end.val);
        node.left = childSort(head, end);
        node.right = childSort(end.next, tail);
        return node;
      }
    };
    var sortedListToBST = function (head) {
      return childSort(head, null);
    };
    

所以这几道题看下来,感觉由xxx生成xxx二叉树的题的思路是一样的,过滤=>找到根节点=>将左右子树递归

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值