6018. 根据描述创建二叉树(dfs)

177 阅读3分钟

Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情

不是因为看到了希望才坚持,而是因为坚持了才能看到希望。共勉

每日刷题第57天 2021.03.07

6018. 根据描述创建二叉树

题目描述

  • 给你一个二维整数数组 descriptions ,其中 descriptions[i] = [parenti, childi, isLefti] 表示 parenti 是 childi 在 二叉树 中的 父节点,二叉树中各节点的值 互不相同 。此外:
  • 如果 isLefti == 1 ,那么 childi 就是 parenti 的左子节点。
  • 如果 isLefti == 0 ,那么 childi 就是 parenti 的右子节点。
  • 请你根据 descriptions 的描述来构造二叉树并返回其 根节点 。
  • 测试用例会保证可以构造出 有效 的二叉树。

提示

解题思路

  • 通过读题可知,当前已经给出了每个相互连接的节点,并且还告知了节点是左节点还是有节点,那么就只需要模拟遍历即可。本题的核心考核点:根节点的查找
  • 之前做过一道题目,有个知识点:根节点的出度和入度(星型图)
  • 对于本题来说,因为是二叉树,因此根节点的出度可以为1或者2或者0,入度则只能为0,因此将入度作为查找根节点的条件。
    • 再仔细想想,入度为0,就表示:根节点只会出现在父节点上,并不会出现在子节点上。(找到根节点)
  • 构建二叉树,使用dfs比较方便。因为每个节点都包含左节点和右节点。
    • 因此可以将大问题(构建二叉树)转化为子问题(构建每个节点的左右节点)

反思

  • 第一次在每次dfs遍历的时候,都去遍历了descriptions数组,查找与当前节点连接的节点。优化:对于每个节点来说,其只有左节点和右节点,那么可以将其用map集合记录下来,类似于图的邻接表,那么每次就只需要遍历与当前节点相连的节点,减少了时间复杂度。

AC代码

/**
 * Definition for a binary tree node.
 * function TreeNode(val, left, right) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.left = (left===undefined ? null : left)
 *     this.right = (right===undefined ? null : right)
 * }
 */
/**
 * @param {number[][]} descriptions
 * @return {TreeNode}
 */
var createBinaryTree = function(descriptions) {
  // 根节点:只存在其指向别的节点,但是没有别的节点指向其
  // 出度为2,入度为0,只需要入度为0
  let len = descriptions.length;
  let map = new Map();
  let mapOne = new Map();
  for(let i = 0; i < len; i++) {
    // 找到根节点 出度为2
    mapOne.set(descriptions[i][0],1);
    mapOne.set(descriptions[i][1],1);
    if(map.has(descriptions[i][1])){
      map.set(descriptions[i][1], map.get(descriptions[i][1]) + 1);
    }else {
      map.set(descriptions[i][1], 0);
    }
  }
  // console.log(mapOne,map);
  let root;
  mapOne.forEach((value, key) => {
   if(!map.has(key)) root = key;
  });
  // console.log(root)
  // 找到根节点
  let treeNode = new TreeNode(root);
  let ans = treeNode;
  function dfs(nodeT) {
    for(let i = 0; i < len; i++) {
      if(descriptions[i][0] == nodeT.val && descriptions[i][2] == 1){
        // 找到左孩子
        let node = new TreeNode(descriptions[i][1]);
        nodeT.left = node;
        dfs(node);
      }else if(descriptions[i][0] == nodeT.val && descriptions[i][2] == 0){
        // 找到右孩子
        let node = new TreeNode(descriptions[i][1]);
        nodeT.right = node;
        dfs(node);
      }
    }
  }
  dfs(treeNode);
  return treeNode;
};

总结

  • 创建二叉树,那么对于每个节点来说,其只有左孩子和右孩子两个节点,因此不需要每次都遍历整个数组,优化处理:提前将每个节点的左右子树保存起来即可。