Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情。
不是因为看到了希望才坚持,而是因为坚持了才能看到希望。共勉
每日刷题第57天 2021.03.07
6018. 根据描述创建二叉树
- leetcode原题链接:leetcode-cn.com/problems/cr…
- 难度:中等
- 方法:dfs
题目描述
- 给你一个二维整数数组 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;
};
总结
- 创建二叉树,那么对于每个节点来说,其只有左孩子和右孩子两个节点,因此不需要每次都遍历整个数组,优化处理:提前将每个节点的左右子树保存起来即可。