LeetCode 每日一题笔记 日期:2026.06.06 题目:2196. 根据描述创建二叉树

LeetCode 每日一题笔记

0. 前言

  • 日期:2026.06.06
  • 题目:2196. 根据描述创建二叉树
  • 难度:中等
  • 标签:二叉树、哈希表、数组

1. 题目理解

问题描述

给定二维数组 descriptions,其中 descriptions[i] = [parent, child, isLeft],表示 parentchild 的父节点。

  • isLeft == 1,则 childparent 的左孩子;
  • isLeft == 0,则 childparent 的右孩子。
    根据描述构造完整二叉树,并返回根节点。

示例

输入:descriptions = [[20,15,1],[20,17,0],[50,20,1],[50,80,0],[80,19,1]]

输出:根节点为 50 的二叉树。

2. 解题思路

核心观察

  • 根节点的关键特征:没有父节点 (不会出现在任何 child 位置)。
  • 可以用数组/哈希表存储所有节点,一次性遍历即可构建完整树结构。

算法步骤

  1. 遍历 descriptions,创建父、子节点并建立左右关系;
  2. 用布尔数组标记所有有父节点的节点;
  3. 遍历节点,找到无父节点的节点作为根返回。

3. 代码实现

java 复制代码
package lc2196;
import java.util.HashSet;

class Solution {
    public class TreeNode {
        int val;
        TreeNode left;
        TreeNode right;

        TreeNode() {
        }

        TreeNode(int val) {
            this.val = val;
        }

        TreeNode(int val, TreeNode left, TreeNode right) {
            this.val = val;
            this.left = left;
            this.right = right;
        }
    }

    public TreeNode createBinaryTree(int[][] descriptions) {
        TreeNode root = new TreeNode(0);
        HashSet<Integer> father = new HashSet<Integer>();
        HashSet<Integer> kid = new HashSet<Integer>();
        int[][] arr = new int[100001][2];

        for (int i = 0; i < descriptions.length; i++) {
            //左孩子
            if (descriptions[i][2] == 1) {
                arr[descriptions[i][0]][0] = descriptions[i][1];
            }
            //右孩子
            else {
                arr[descriptions[i][0]][1] = descriptions[i][1];
            }
            kid.add(descriptions[i][1]);
        }

        for (int i = 0; i < descriptions.length; i++) {
            if (!kid.contains(descriptions[i][0])) {
                root.val = descriptions[i][0];
            }
        }

        method1(root, arr, arr[root.val][0], arr[root.val][1]);

        return root;
    }

    private void method1(TreeNode root, int[][] arr, int left, int right) {
        if (left != 0) {
            root.left = new TreeNode(left);
            method1(root.left, arr, arr[left][0], arr[left][1]);
        }

        if (right != 0) {
            root.right = new TreeNode(right);
            method1(root.right, arr, arr[right][0], arr[right][1]);
        }

    }
}

4. 代码优化说明

java 复制代码
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
public TreeNode createBinaryTree(int[][] descriptions) {
    // 数组存储所有节点,下标对应节点值
    TreeNode[] nodes = new TreeNode[100001];
    // 标记节点是否存在父节点
    boolean[] existParent = new boolean[100001];

    for (int[] description : descriptions) {
        // 父节点不存在则创建
        if (nodes[description[0]] == null) {
            nodes[description[0]] = new TreeNode(description[0]);
        }
        // 子节点不存在则创建
        if (nodes[description[1]] == null) {
            nodes[description[1]] = new TreeNode(description[1]);
        }
        // 建立左右孩子关系
        if (description[2] == 1) {
            nodes[description[0]].left = nodes[description[1]];
        } else {
            nodes[description[0]].right = nodes[description[1]];
        }
        // 标记子节点已有父节点
        existParent[description[1]] = true;
    }

    // 遍历找到无父节点的根节点
    for (int i = 0; i < 100001; i++) {
        if (nodes[i] != null && !existParent[i]) {
            return nodes[i];
        }
    }
    return null;
}
}

5. 复杂度分析

  • 时间复杂度 :O(n)O(n)O(n),两次线性遍历(一次构建节点关系,一次找根节点)。
  • 空间复杂度 :O(n)O(n)O(n),主要为节点数组和标记数组的开销。

6. 总结

  • 核心思路:通过标记"无父节点"找到根节点,同时一次性构建树结构
  • 优化点:用数组直接存储节点,避免递归构建,减少分支判断,逻辑更简洁高效。
  • 关键技巧:根节点的识别方法是这类题的核心,利用"不会出现在子节点位置"这一特征快速定位。
相关推荐
rannn_1114 小时前
【力扣hot100】链表专题|160、206、234、141、142
java·算法·leetcode·链表·面试·开发
数模竞赛Paid answer5 小时前
2026年华东杯数学建模B题医药物流安排问题解题全过程文档及程序
算法·数学建模·数据分析·华东杯
不会代码的小猴5 小时前
21. 泛型编程上
开发语言·c++·笔记·算法
营养充电站5 小时前
VS Code Git 工作树:解锁多分支并行开发的高效体验
leetcode·决策树·逻辑回归·散列表·模拟退火算法
AI备案指南-满满6 小时前
大模型与算法备案全流程详解:从零到通过的完整指南
人工智能·算法·备案·大模型备案·算法备案
江畔柳前堤6 小时前
LLM 训练核心机制深度解析:Warmup、Cosine Decay 与 Perplexity 的完整知识体系
网络·人工智能·深度学习·算法·机器学习·语音识别
一只旭宝6 小时前
细讲C加加【9】C++ std::function与std::bind详解|仿函数、绑定器、类成员绑定、占位符、成员偏移指针
开发语言·c++·算法
良木林7 小时前
子串 - LeetCode hot 100
算法·leetcode·职场和发展
摇滚侠7 小时前
《SpringBoot 3:入门与应用实战》第 2 章 IOC 思想与实现 阅读笔记 1
spring boot·笔记·后端