LeetCode | 1361. Validate Binary Tree Nodes(Union-Find one-way edge C++)

题目描述(中等难度)

原题链接
在这里插入图片描述

算法

(并查集) O ( n ) O(n)

(1)初始化n个连通集,让每个结点的祖宗结点是它本身
(2)设要加的边是a->b,我们判断下,如果 a a b b 的祖宗相等,说明你加上这条边会形成环,返回false,如果不相等,继续往下判断
(3)因为这里是单向边,如果像示例2的结点3一样有两个结点指向它,也是不成立的,所以我们在(2)的基础上还有判断箭头指向的结点 b b 原来是否有其他结点指向它,如果有则返回false,否则将 b b 加到 a a 所在的连通集中,即p[pb] = pa;
(4)最后判断连通块的个数是否为 1 1 即可

时间复杂度是 O ( n ) O(n) :并查集的查找和合并操作的复杂度是近乎 O ( 1 ) O(1) 的,空间复杂度是 O ( n ) O(n)

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是因为题目的测试样例不好

而且判题机显示的预期结果也是错误的
在这里插入图片描述


写在最后:我的博客主要是对计算机领域所学知识的总结、回顾和思考,把每篇博客写得通俗易懂是我的目标,分享技术和知识是一种快乐 ,非常欢迎大家和我一起交流学习,有任何问题都可以在评论区留言,也期待与您的深入交流(^∀^●)

发布了270 篇原创文章 · 获赞 111 · 访问量 11万+

猜你喜欢

转载自blog.csdn.net/qq_43827595/article/details/104465570