题目描述(中等难度)
算法
(并查集)
(1)初始化n个连通集,让每个结点的祖宗结点是它本身
(2)设要加的边是a->b
,我们判断下,如果
和
的祖宗相等,说明你加上这条边会形成环,返回false
,如果不相等,继续往下判断
(3)因为这里是单向边,如果像示例2的结点3一样有两个结点指向它,也是不成立的,所以我们在(2)的基础上还有判断箭头指向的结点
原来是否有其他结点指向它,如果有则返回false
,否则将
加到
所在的连通集中,即p[pb] = pa;
(4)最后判断连通块的个数是否为
即可
时间复杂度是 :并查集的查找和合并操作的复杂度是近乎 的,空间复杂度是
C++代码
class Solution {
public:
static const int N = 1e4 + 7;
int p[N];
int find(int x) {
if (p[x] != x) p[x] = find(p[x]);
return p[x];
}
bool validateBinaryTreeNodes(int n, vector<int>& leftChild, vector<int>& rightChild) {
for (int i = 0; i < n; i ++) p[i] = i;
for (int i = 0; i < n; i ++) {
// i->leftChild[i]
int Left = leftChild[i];
if (Left != -1) {
int pa = find(i), pb = find(Left);
if (pa == pb) return false; // 两个结点祖先相同
else {
if (pb == Left)
p[pb] = pa;
else // 箭头指向的结点已经有别的结点指向了,如示例2:结点3
return false;
}
}
int Right = rightChild[i];
if (Right != -1) {
int pa = find(i), pb = find(Right);
if (pa == pb) return false;
else {
if (pb == Right)
p[pb] = pa;
else
return false;
}
}
}
// 统计连通块个数
int ans = 0;
for (int i = 0; i < n; i ++) {
if (p[i] == i) ans ++;
}
return ans == 1;
}
};
错误代码示范
二叉树的空指针个数是n+1,但空指针个数是n+1不一定是二叉树
如下面样例
3
[1,0,-1]
[-1,-1,-1]
class Solution {
public:
bool validateBinaryTreeNodes(int n, vector<int>& leftChild, vector<int>& rightChild) {
int num = 0;
for (int i = 0; i < n; i ++) {
num += (leftChild[i] == -1) + (rightChild[i] == -1);
}
return num == n + 1;
}
};
之所以上面代码能AC是因为题目的测试样例不好
而且判题机显示的预期结果也是错误的
写在最后:我的博客主要是对计算机领域所学知识的总结、回顾和思考,把每篇博客写得通俗易懂是我的目标,分享技术和知识是一种快乐 ,非常欢迎大家和我一起交流学习,有任何问题都可以在评论区留言,也期待与您的深入交流(^∀^●)