DFS leetcode-547 朋友圈

DFS->547 朋友圈

班上有 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。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/friend-circles
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。


第一次写思路:

由于好友具有传递性,可以使用DFS将每个学生的朋友圈找出来,并且设置为0,计数器+1,最终计数器数就是朋友圈数。

矩阵每一行表示这个学生和其他学生的关系,遍历每个学生x通过矩阵的x行判断他的其他好友。每次搜索到新关系都将新关系标记变为0,如果发现有其他好友,就再对这个好友进行递归搜索,找到这个好友的其他好友,最终把x的朋友圈都找出来,count++

代码

效率很低

class Solution {
    public int findCircleNum(int[][] M) {

        int i,j;
        int count = 0;
        for(i=0;i<M.length;i++){
            if( M[i][i] == 1 ){
                count++;
                dfs(M,i);
            }
        }
        return count;

    }

    public void dfs(int[][] martrix,int x){

        int i,j;

        martrix[x][x] = 0;

        for(i=0;i<martrix.length;i++){
            if( martrix[x][i] == 0 )
                continue;
            martrix[x][i] = 0;    
            dfs(martrix,i);
        }
    }


}

题解解法一:

题目可以看成查找连通块,将每个同学看作一个节点,每个朋友圈就是一个连通块。于是,对每个同学x使用DFS,查找x关系的连通块,每次查找count++,最终count数就是朋友圈数

实现思路:

使用一个标记数组,表示每个节点是否被访问过。

使用DFS,对每个节点查找他的连通块,统计连通块个数。

class Solution {
    public int findCircleNum(int[][] M) {
        int i,j;
        int count = 0;
        int[] visited = new int[M.length];
        for(i=0;i<M.length;i++){
            if( visited[i] == 0 ){
                count++;
                dfs(M,visited,i);
            }
        }
        return count;
    }

    //查找x的连通块
    public void dfs(int[][] martrix,int[] visited,int x){
        int i;
        for(i=0;i<martrix.length;i++){
            if( martrix[x][i] == 1 && visited[i] == 0 ){
                visited[i] = 1;
                dfs(martrix,visited,i);
            }
        }
    }
}

题解解法三:并查集

还没学过


总结:

最近做的题目很少,题解一的思路和自己写的思路有一些相似的地方, 但是自己在实现的时候是利用原矩阵进行标记,而题解是使用了一个标记数组。另外,题解在分析时将题目转换成了图来理解,自己在写的时候没考虑那么多,直接就写,做题的经验也不足,效率太低。
以后分析这类问题也要将问题转换成图来考虑,实现的时候要注意运行效率。

原文地址:https://www.cnblogs.com/ELAIRS/p/12753420.html