1361. 验证二叉树
一、题目
二叉树上有 n
个节点,按从 0
到 n - 1
编号,其中节点 i
的两个子节点分别是 leftChild[i]
和 rightChild[i]
。
只有 所有 节点能够形成且 只 形成 一颗 有效的二叉树时,返回 true
;否则返回 false
。
如果节点 i
没有左子节点,那么 leftChild[i]
就等于 -1
。右子节点也符合该规则。
注意:节点没有值,本问题中仅仅使用节点编号。
二、思路
- 除了检测环和连通分支数,我们还需要进行一些特殊的判断,例如一个孩子存在多个父亲,一个父亲的存在两个相同的孩子。
三、代码
class Solution { // 并查集用的集合列表 List<Integer> p = new ArrayList<>(); // 用于统计不相交的连通分支个数 int cnt; public boolean validateBinaryTreeNodes(int n, int[] leftChild, int[] rightChild) { // 用于标记各个孩子的父节点 int[] father = new int[n]; // 初始化 Arrays.fill(father, -1); // 初始化并查集集合状态 for(int i = 0; i < n; i++) p.add(i); // 初始化分支数 cnt = n; // 遍历所有节点 for(int i = 0; i < n; i++) { // 如果节点存在两个孩子,而且两个孩子相同,那么显然是错误的二叉树 if(leftChild[i] == rightChild[i] && leftChild[i] != -1) return false; // 合并两个孩子 if(!merge(father, i, leftChild[i]) || !merge(father, i, rightChild[i])) return false; } // 如果最后所有的节点组成一个连通分支,才是一棵树 if(cnt == 1) return true; return false; } // 和并父亲和孩子节点,并判断逻辑 private boolean merge(int[] father, int f, int c) { // 孩子是空的,直接返回 if(c == -1) return true; // 孩子之前有爸爸了,就是错的 if(father[c] != -1) return false; // 并查集查找两个集合的根 int a = find(f), b = find(c); // 如果孩子和父亲已经存在于一个集合中,那么说明会产生环,返回错误 if(a == b) return false; // 合并两个集合 p.set(a, b); // 标记孩子的父亲是谁 father[c] = f; // 连通分支数减一 cnt --; return true; } // 并查集通用方法,找集合的根元素 private int find(int x) { if(p.get(x) != x) { p.set(x, find(p.get(x))); } return p.get(x); } }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了