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. OC 字典dictionaryWithObjectsAndKeys报错

    字典dictionaryWithObjectsAndKeys crash,也没有控制台打印输出: 解决方案!! 1.检查dictionaryWithObjectsAndKeys中的object key ...

  2. 阿里开源 Dragonwell JDK 重磅发布 GA 版本:生产环境可用

    今年 3 月份,阿里巴巴重磅开源 OpenJDK 长期支持版本 Alibaba Dragonwell的消息,在很长一段时间内都是开发者的讨论焦点,该项目在 Github 上的 Star 数迅速突破 1 ...

  3. 1. mvc 树形控件tree + 表格jqgrid 显示界面

    1.界面显示效果 2.资源下载 地址 1. jstree  https://www.jstree.com/   2.表格jqgrid  https://blog.mn886.net/jqGrid/  ...

  4. C#中的一些对话框问题处理

    1. 对于打开文件对话框处理 #region 打开文件对话框 string StrPath; OpenFileDialog Flag = new OpenFileDialog(); Flag.Mult ...

  5. python 处理中文遇到的编码问题总结 以及 字符str的编码如何判断

    如何处理中午编码的问题 Python的UnicodeDecodeError: 'utf8' codec can't decode byte 0xxx in position 这个错误是因为你代码中的某 ...

  6. 面试前必须要知道的21道Redis面试题

    1.使用redis有哪些好处? 速度快,因为数据存在内存中,类似于HashMap,HashMap的优势就是查找和操作的时间复杂度都是O(1) 支持丰富数据类型,支持string,list,set,so ...

  7. 2019 梆梆安全java面试笔试题 (含面试题解析)

      本人5年开发经验.18年年底开始跑路找工作,在互联网寒冬下成功拿到阿里巴巴.今日头条.梆梆安全等公司offer,岗位是Java后端开发,因为发展原因最终选择去了梆梆安全,入职一年时间了,也成为了面 ...

  8. AOD.NET实现数据库事物Transaction

    在开始介绍文章主要内容前先简单说一下事务 1.事务介绍 事务是一种机制.是一种操作序列,它包含了一组数据库操作命令,这组命令要么全部执行,要么全部不执行.因此事务是一个不可分割的工作逻辑单元.在数据库 ...

  9. RV64I基础整数指令集

    RV64I是RV32I的超集,RV32I是RV64I的子集.RV64I包括RV32I的所有40条指令,另外增加了12条RV32I中没有的指令,还有三条移位指令(slli, srli,srai)也进行小 ...

  10. python学习3-python views.py的返回值

    2.首先要说明一点是,对于HttpRequest对象来说,是Django自己创建的,但是HttpResponse就必须要我们自己创建.注意每个view方法都必须返回一个HttpResponse对象,H ...