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. 总结

  • 核心思路:通过标记"无父节点"找到根节点,同时一次性构建树结构
  • 优化点:用数组直接存储节点,避免递归构建,减少分支判断,逻辑更简洁高效。
  • 关键技巧:根节点的识别方法是这类题的核心,利用"不会出现在子节点位置"这一特征快速定位。
相关推荐
小欣加油1 小时前
leetcode994 腐烂的橘子
数据结构·c++·算法·leetcode·bfs
.千余2 小时前
【C++】手写双向链表:list容器模拟实现
开发语言·c++·笔记·学习·其他
QuZero2 小时前
Guava Cache Deep Dive
java·后端·算法·guava
随意起个昵称2 小时前
线性dp-LIS题目4(A Twisty Movement)
算法·动态规划
Felven2 小时前
B. Fair Numbers
数据结构·算法
人道领域2 小时前
【LeetCode刷题日记】93.复原IP地址
java·开发语言·算法·leetcode
jarreyer2 小时前
【算法记录1】模型训练问题
算法
Felven3 小时前
D. Friends and the Restaurant
算法
想吃火锅10053 小时前
【leetcode】165.比较版本号js
javascript·算法·leetcode