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   itdef  阅读(224)  评论(0编辑  收藏  举报

编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话
历史上的今天:
2016-05-24 字典类的代码的学习

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

统计

点击右上角即可分享
微信分享提示