zoukankan      html  css  js  c++  java
  • 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驱动爱好者 服务器程序员沟通交流
    如果觉得不错,欢迎点赞,你的鼓励就是我的动力
    阿里打赏 微信打赏
  • 相关阅读:
    11. Container With Most Water
    9. Palindrome Number
    375. 猜数字大小 II leetcode java
    leetcode 72 编辑距离 JAVA
    73. 矩阵置零 leetcode JAVA
    快速排序 JAVA实现
    63. 不同路径 II leetcode JAVA
    重写(override)与重载(overload)
    62 不同路径 leetcode JAVA
    leetcode 56 合并区间 JAVA
  • 原文地址:https://www.cnblogs.com/itdef/p/10919862.html
Copyright © 2011-2022 走看看