朋友圈
班上有 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。
注意:
- N 在[1,200]的范围内。
- 对于所有学生,有M[i][i] = 1。
- 如果有M[i][j] = 1,则有M[j][i] = 1。
解题思路:
朋友圈问题与岛屿问题类似,但是不同,岛屿问题,在找岛屿时需要上下左右四个方向相连则为岛屿,而朋友全问题则是以靠关系的矢量来确立朋友圈,也就是说,即使两个人的关系图没有直接相连,也可能在同一个朋友圈。
1.依照题目意思,第一步可以建立一个数组用于标记当前学生是否已经被访问过。
2.第二步,对二维关系数组进行遍历,每一行代表一个学生,每一列代表和第j个学生的关系,判断当前学生是否访问过,若访问过,则继续下一次循环。若没有访问过,进入递归,并将朋友圈个数+1
3.递归过程,递归过程实际上是找当前当前朋友圈里面的所有人,因此,对当前进入递归的同学的关系网进行遍历,需要关系状态为1并且同时没有被访问过,才进入下一次递归,直到遍历完所有同学,则自动跳出循环。返回count即为朋友圈个数
class Solution {public int findCircleNum(int[][] M) {// 人数int peopleCount = M.length;int[] visited = new int[peopleCount]; // 开辟访问,用于标记该学生是否已经被访问过int count = 0;for (int i = 0; i < peopleCount; i++){if (visited[i] == 0){ // 当前同学没被访问过,那么递归遍历学生的关系网(即有多少个关系为1的)dfs(M, visited, i, peopleCount);count++;}}return count;}private void dfs(int[][] M, int[] visited, int i, int peopleCount){for (int j = 0; j < peopleCount; j++){// 遍历当前同学的关系网,判断是否为朋友,并判断是否已经被访问过,被访问过,即为已在某个朋友圈内if (M[i][j] == 1 && visited[j] == 0){// 若当前关系为1,即两人互为好友,且当前没有被访问过,则设置访问状态为1,继续将J传入进行递归调用visited[j] = 1;dfs(M, visited, j, peopleCount);}}}}
