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

 

posted on 2019-05-24 19:32  itdef  阅读(219)  评论(0编辑  收藏  举报

导航