leetcode 547. 朋友圈

题目描述:

班上有 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: 一开始以为只需要求图的连通分量个数就好了,就仿照之前岛屿的数量那道题做,利用dfs完成。结果出现了样例错误才知道这道题的真正题意。将原来的代码进行修改,这里的visited数组只需要是一维,对应每个人是否被访问过。对于每一个未被访问的人,进行dfs。dfs函数中,首先标记当前人被访问,接下来遍历他的朋友,若未被访问,则逐层深度访问其朋友。

 

思路2: 利用并查集实现。首先有n个对应其朋友圈编号为其本身,此时总的朋友圈数为人的总数。接下来遍历每个关系对,若i和j是朋友,分别获取i和j的朋友圈编号,若不一致,将i的朋友圈编号改为j,即合并两个人的朋友圈,朋友圈总数减1。遍历完成后,所得的朋友圈数即为总数。

 

代码:

 1 class Solution {
 2 public:
 3     void dfs(vector<vector<int>>& M, vector<int>& visited, int idx)
 4     {
 5         visited[idx] = 1;
 6         for(int j=0; j<M.size(); j++)
 7         {
 8             if(idx == j)
 9                 continue;
10             if(visited[j] == 0 && M[idx][j])
11             {
12                 dfs(M, visited, j);
13             }
14         }
15     }
16     int findCircleNum(vector<vector<int>>& M) {
17         if(M.size() == 0)
18             return 0;
19         vector<int> visited(M.size(), 0);
20         int cnt = 0;
21         for(int i=0; i<M.size(); i++)
22         {
23             if(visited[i] == 0 )
24             {
25                 cnt++;
26                 dfs(M, visited, i);
27             }
28         }
29         return cnt;
30     }
31 };

 

思路2:

 1 class Solution {
 2 public:
 3     int find(vector<int>& pre, int x)
 4     {
 5         return pre[x] == x ? x:find(pre, pre[x]);
 6     }
 7     int findCircleNum(vector<vector<int>>& M) {
 8         if(M.size() == 0)
 9             return 0;
10         vector<int> pre(M.size(), 0);
11         for(int i=0; i<M.size(); i++)
12             pre[i] = i;
13         int group = M.size();
14         for(int i=0; i<M.size(); i++)
15         {
16             for(int j=0; j<M[i].size(); j++)
17             {
18                 if(i!=j && M[i][j])
19                 {
20                     int x1 = find(pre, i);
21                     int x2 = find(pre, j);
22                     if(x1 != x2)
23                     {
24                         pre[x1] = x2;
25                         group--;
26                     }
27                 }
28             }
29         }
30         return group;
31     }
32 };

 

转载于:https://www.cnblogs.com/LJ-LJ/p/11222885.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值