• LeetCode 547. 朋友圈


    习题地址  https://leetcode-cn.com/problems/friend-circles/

    班上有 N 名学生。其中有些人是朋友,有些则不是。他们的友谊具有是传递性。如果已知 A 是 B 的朋友,B 是 C 的朋友,那么我们可以认为 A 也是 C 的朋友。所谓的朋友圈,是指所有朋友的集合。

    给定一个 N * N 的矩阵 M,表示班级中学生之间的朋友关系。如果M[i][j] = 1,表示已知第 i 个和 j 个学生互为朋友关系,否则为不知道。你必须输出所有学生中的已知的朋友圈总数。

    示例 1:

    输入: 
    [[1,1,0],
     [1,1,0],
     [0,0,1]]
    输出: 2 
    说明:已知学生0和学生1互为朋友,他们在一个朋友圈。
    第2个学生自己在一个朋友圈。所以返回2。

    示例 2:

    输入: 
    [[1,1,0],
     [1,1,1],
     [0,1,1]]
    输出: 1
    说明:已知学生0和学生1互为朋友,学生1和学生2互为朋友,所以学生0和学生2也是朋友,所以他们三个在一个朋友圈,返回1。

    注意:

    1. N 在[1,200]的范围内。
    2. 对于所有学生,有M[i][i] = 1。
    3. 如果有M[i][j] = 1,则有M[j][i] = 1。

    解答

    并查集常规用法

    并查集简介

     

    数组中的每个数字都指向自己 然后根据从属关系 将数组指向进行改变。

    同一组的元素的顶端元素是一样。与图中稍有区别的是

    元素1 和2的 顶端都是0

     int union[1000];
    
        void init(int n)
        {
            for (int i = 0; i < 1000; i++)
                union[i] = i;
        }    
    //代码实现
    //得到元素所在集合的最顶端
        int get(int x)
        {
            return x == euqal[x] ? x : euqal[x] = get(euqal[x]);
        }
    //将两个集合合并在一起
        void merge(int x, int y)
        {
            euqal[get(x)] = get(y);
        }

    但是不适当的合并 容易造成单链的集合 查找链表最低端的元素属于哪个集合(得到集合顶端元素) 可能会是一个漫长的过程

    比如下图的5元素 要遍历整个集合的全部元素才能达到顶端。

    所以合并的时候 会尽量将合并的上级元素的指向 指向顶点元素

     1 class UnionFind {
     2 public:
     3     vector<int> father;
     4     UnionFind(int num) {
     5         for (int i = 0; i < num; i++) {
     6             father.push_back(i);    //每个人都指向自己
     7         }
     8     }
     9     int Find(int n) {
    10         //非递归版本 
    11         /*
    12         while (father[n] != n) {
    13             n = father[n];
    14         }
    15         return n;
    16         */
    17         //递归
    18         if (father[n] == n)
    19             return n;
    20         father[n] = Find(father[n]);
    21         return father[n] ;
    22     }
    23     void Union(int a, int b) {
    24         int fa = Find(a);
    25         int fb = Find(b);
    26         father[fb] = fa;
    27     }
    28 };
    29 
    30 class Solution {
    31 public:
    32     int findCircleNum(vector<vector<int>>& M) {
    33         int N = M.size();
    34         UnionFind UF(N);
    35         for(int i =0;i < N;i++){
    36             for(int j =0;j<N;j++){
    37                 if(M[i][j]){
    38                     UF.Union(i,j);
    39                 }
    40             }
    41         }
    42         int res = 0;
    43         for(int i=0;i < N;i++){
    44             if(UF.Find(i) == i)
    45                 res++;
    46         }
    47         return res;
    48     }
    49 };
    View Code
    作 者: itdef
    欢迎转帖 请保持文本完整并注明出处
    技术博客 http://www.cnblogs.com/itdef/
    B站算法视频题解
    https://space.bilibili.com/18508846
    qq 151435887
    gitee https://gitee.com/def/
    欢迎c c++ 算法爱好者 windows驱动爱好者 服务器程序员沟通交流
    如果觉得不错,欢迎点赞,你的鼓励就是我的动力
    阿里打赏 微信打赏
  • 相关阅读:
    Enum, Generic and Templates
    Writing A Threadpool in Rust
    A First Look at Rust Language
    Closures in OOC
    Complexity Behind Closure
    Introduction to OOC Programming Language
    OOC,泛型,糟糕的设计。
    Enlightenment笔记
    Machine Learning/Random Projection
    Machine Learning/Introducing Logistic Function
  • 原文地址:https://www.cnblogs.com/itdef/p/10919862.html
Copyright © 2020-2023  润新知