There are N students in a class. Some of them are friends, while some are not. Their friendship is transitive in nature. For example, if A is a direct friend of B, and B is a direct friend of C, then A is an indirect friend of C. And we defined a friend circle is a group of students who are direct or indirect friends.

Given a N*N matrix M representing the friend relationship between students in the class. If M[i][j] = 1, then the ithand jth students are direct friends with each other, otherwise not. And you have to output the total number of friend circles among all the students.

Example 1:

Input:
[[1,1,0],
[1,1,0],
[0,0,1]]
Output: 2
Explanation:The 0th and 1st students are direct friends, so they are in a friend circle.
The 2nd student himself is in a friend circle. So return 2.

Example 2:

Input:
[[1,1,0],
[1,1,1],
[0,1,1]]
Output: 1
Explanation:The 0th and 1st students are direct friends, the 1st and 2nd students are direct friends,
so the 0th and 2nd students are indirect friends. All of them are in the same friend circle, so return 1.

Note:

  1. N is in range [1,200].
  2. M[i][i] = 1 for all students.
  3. If M[i][j] = 1, then M[j][i] = 1.

这道题让我们求朋友圈的个数,题目中对于朋友圈的定义是可以传递的,比如A和B是好友,B和C是好友,那么即使A和C不是好友,那么他们三人也属于一个朋友圈。那么比较直接的解法就是 DFS 搜索,对于某个人,遍历其好友,然后再遍历其好友的好友,那么就能把属于同一个朋友圈的人都遍历一遍,同时标记出已经遍历过的人,然后累积朋友圈的个数,再去对于没有遍历到的人在找其朋友圈的人,这样就能求出个数。其实这道题的本质是之前那道题 Number of Connected Components in an Undirected Graph,其实许多题目的本质都是一样的,就是看我们有没有一双慧眼能把它们识别出来:

解法一:

class Solution {
public:
int findCircleNum(vector<vector<int>>& M) {
int n = M.size(), res = ;
vector<bool> visited(n, false);
for (int i = ; i < n; ++i) {
if (visited[i]) continue;
helper(M, i, visited);
++res;
}
return res;
}
void helper(vector<vector<int>>& M, int k, vector<bool>& visited) {
visited[k] = true;
for (int i = ; i < M.size(); ++i) {
if (!M[k][i] || visited[i]) continue;
helper(M, i, visited);
}
}
};

我们也可以用 BFS 来遍历朋友圈中的所有人,解题思路和上面大同小异,参见代码如下:

解法二:

class Solution {
public:
int findCircleNum(vector<vector<int>>& M) {
int n = M.size(), res = ;
vector<bool> visited(n, false);
queue<int> q;
for (int i = ; i < n; ++i) {
if (visited[i]) continue;
q.push(i);
while (!q.empty()) {
int t = q.front(); q.pop();
visited[t] = true;
for (int j = ; j < n; ++j) {
if (!M[t][j] || visited[j]) continue;
q.push(j);
}
}
++res;
}
return res;
}
};

下面这种解法叫联合查找 Union Find,也是一种很经典的解题思路,在之前的两道道题 Graph Valid Tree 和 Number of Connected Components in an Undirected Graph 中也有过应用,核心思想是初始时给每一个对象都赋上不同的标签,然后对于属于同一类的对象,在 root 中查找其标签,如果不同,那么将其中一个对象的标签赋值给另一个对象,注意 root 数组中的数字跟数字的坐标是有很大关系的,root 存的是属于同一组的另一个对象的坐标,这样通过 getRoot 函数可以使同一个组的对象返回相同的值,参见代码如下:

解法三:

class Solution {
public:
int findCircleNum(vector<vector<int>>& M) {
int n = M.size(), res = n;
vector<int> root(n);
for (int i = ; i < n; ++i) root[i] = i;
for (int i = ; i < n; ++i) {
for (int j = i + ; j < n; ++j) {
if (M[i][j] == ) {
int p1 = getRoot(root, i);
int p2 = getRoot(root, j);
if (p1 != p2) {
--res;
root[p2] = p1;
}
}
}
}
return res;
}
int getRoot(vector<int>& root, int i) {
while (i != root[i]) {
root[i] = root[root[i]];
i = root[i];
}
return i;
}
};

Github 同步地址:

https://github.com/grandyang/leetcode/issues/547

类似题目:

Accounts Merge

Redundant Connection II

Redundant Connection

Number of Islands II

Graph Valid Tree

Number of Connected Components in an Undirected Graph

Similar String Groups

参考资料:

https://leetcode.com/problems/friend-circles/

https://leetcode.com/problems/friend-circles/discuss/101440/c-bfs

https://leetcode.com/problems/friend-circles/discuss/101338/Neat-DFS-java-solution

https://leetcode.com/problems/friend-circles/discuss/101387/Easy-Java-Union-Find-Solution

LeetCode All in One 题目讲解汇总(持续更新中...)

[LeetCode] 547. Friend Circles 朋友圈的更多相关文章

  1. LeetCode 547. Friend Circles 朋友圈(C++/Java)

    题目: https://leetcode.com/problems/friend-circles/ There are N students in a class. Some of them are ...

  2. [LeetCode]547. Friend Circles朋友圈数量--不相邻子图问题

    /* 思路就是遍历所有人,对于每一个人,寻找他的好友,找到好友后再找这个好友的好友 ,这样深度优先遍历下去,设置一个flag记录是否已经遍历了这个人. 其实dfs真正有用的是flag这个变量,因为如果 ...

  3. 547 Friend Circles 朋友圈

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

  4. [LeetCode] Friend Circles 朋友圈

    There are N students in a class. Some of them are friends, while some are not. Their friendship is t ...

  5. Leetcode547: Friend Circles 朋友圈问题

    问题描述 在一个班级里有N个同学, 有些同学是朋友,有些不是.他们之间的友谊是可以传递的比如A和B是朋友,B和C是朋友,那么A和C也是朋友.我们定义 friend circle为由直接或者间接都是朋友 ...

  6. Leetcode之深度优先搜索(DFS)专题-547. 朋友圈(Friend Circles)

    Leetcode之深度优先搜索(DFS)专题-547. 朋友圈(Friend Circles) 深度优先搜索的解题详细介绍,点击 班上有 N 名学生.其中有些人是朋友,有些则不是.他们的友谊具有是传递 ...

  7. Java实现 LeetCode 547 朋友圈(并查集?)

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

  8. [LeetCode]547. 朋友圈(DFS)

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

  9. LeetCode 547 朋友圈

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

随机推荐

  1. mysql百万级数据分页查询缓慢优化-实战

    作为后端攻城狮,在接到分页list需求的时候,内心是这样的 画面是这样的 代码大概是这样的 select count(id) from …       查出总数 select * from …. li ...

  2. python Condition

    import threading # 必须要使用condition的例子 # class XiaoAi(threading.Thread):# def __init__(self, lock):# s ...

  3. 使用Redis作为Spring Security OAuth2的token存储

    写在前边 本文对Spring Security OAuth2的token使用Redis保存,相比JWT实现的token存储,Redis可以随时吊销access_token,并且Redis响应速度很快, ...

  4. Pandas 学习 第9篇:DataFrame - 数据的输入输出

    常用的数据存储介质是数据库和csv文件,pandas模块包含了相应的API对数据进行输入和输出: 对于格式化的平面文件:read_table() 对于csv文件:read_csv().to_csv() ...

  5. [CrackMe]160个CrackMe之001

    吾爱破解专题汇总:[反汇编练习]160个CrackME索引目录1~160建议收藏备用 一.Serial/Name 之 暴力破解 1. 熟悉界面:很常规的一个界面,输入完账号密码之后会进行验证.  2. ...

  6. C# 方法的out、ref、params参数

    一.out参数实例 [实例]求一个数组中的最大值.最小值.总和.平均值 class Program { static void Main(string[] args) { //写一个方法 求一个数组中 ...

  7. Winform中设置多条Y轴时新增的Y轴刻度不显示问题解决

    场景 Winform中实现ZedGraph的多条Y轴(附源码下载): https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/1001322 ...

  8. deepin添加设置快捷键

    deepin的设置侧边栏没有快捷键需要手动设置,第一步就是要知道设置的命令是什么. 按下start,把其中的"控制中心"发送到桌面,以文本方式打开之,其中的exec字段就是打开设置 ...

  9. maven Could not resolve dependencies

    错误语句 Could not resolve dependencies for project weiyinfu:poemqa:jar:1.0: The following artifacts cou ...

  10. cross validation交叉验证

    交叉验证是一种检测model是否overfit的方法.最常用的cross validation是k-fold cross validation. 具体的方法是: 1.将数据平均分成k份,0,1,2,, ...