参考文章:
DFS
使用深度优先遍历(dfs),如果学生 A 与 B 是好友,则 A 肯定也与 B 的好友圈的任意学生也是好友关系,即有传递性,因此,在遍历到 A 与 B 是好友的时候,还要遍历 B 的好友,以及 B 的好友的好友,即会最终把跟 A 处于同一圈子的人在同一轮中都遍历到。。
// 递归的实现方法
public int findCircleNum(int[][] M) {
if (M == null || M.length==0 ||M[0] == null || M[0].length == 0) return 0;
int count = 0;
int book[] = new int[M.length];// 辅助数组
for (int i = 0; i < M.length; i++) {
// 如果 book[i] 为 0,则表示该学生与之前的学生 (i-1) 不是在同一个圈子的(与 i-2 也是如此),因此 count++
// 因为如果 (i-1) 与 i 是一个圈子的,则在遍历学生 (i-1) 与学生 (i-1) 的朋友,或者朋友的朋友... 的时候,
// 最终也会遍历到学生 i,此时 book[i] 同样也会被置为 1
if (book[i] == 0) {
book[i] = 1;
dfs(M, i, book);
count++;
}
}
return count;
}
public void dfs(int[][] M, int i, int[] book){
for (int j = 0; j < M.length; j++){
// M[i][j],其中 i 是固定的(第 i 列)
// 即遍历学生 i 的朋友,如果学生 i 与 j 是朋友且学生 j 的朋友圈还没有被遍历(即 book[j] 还为 0 ),则再遍历 j 的朋友
// 而如果 book[j] 已经为 1 了,则表示之前已经探明了学生 i 与 j 处于同一圈子(可能是间接的,但是间接的也每没有影响)
if (M[i][j] == 1 && book[j] == 0){
book[j] = 1;
dfs(M, j, book);
}
}
}
BFS
// 迭代的实现方法
public int findCircleNum(int[][] M) {
if (M == null || M.length==0 ||M[0] == null || M[0].length == 0) return 0;
int count = 0;
int book[] = new int[M.length];// 辅助数组
LinkedList<Integer> queue = new LinkedList<>();//借助一个队列
for (int i = 0; i < M.length; i++) {
if (book[i]==1) continue;
queue.push(i);
while (!queue.isEmpty()) {
int v = queue.pop();
book[v] = 1;
for (int j = 0; j < M.length; j++) {
// v 固定,先访问与 v 相邻的,把符合条件的先收集到队列中
if (M[v][j] == 1 && book[j] == 0) {
queue.push(j);
}
}
}
count++;
}
return count;
}
这里采用的是 BFS,与 DFS 的区别是:
-
DFS 是在遍历到 A 与 B 为好友时,就会先把 B 的好友以及好友的好友等都遍历一遍。
-
而 BFS 会在遍历到 A 与 B 为好友时,先把 B 收集起来,先遍历完 A 的所有好友,再去处理之后的逻辑。