【探索-字节跳动】朋友圈

在这里插入图片描述
参考文章:

  1. Leetcode学习笔记-547-朋友圈
  2. [LeetCode] Friend Circles 朋友圈
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 的所有好友,再去处理之后的逻辑。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值