Leetcode 547. Friend Circles(python+cpp)

该博客探讨LeetCode 547题,涉及寻找无向图连通分量的问题。尽管与695题在矩阵表示上有所不同,但解题思路相似。博主分析了DFS和BFS两种方法,指出虽然两者时间复杂度相同,但在实际运行中DFS表现更优。此外,还提供了C++实现的DFS解法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Leetcode 547. Friend Circles

题目

在这里插入图片描述

解析

这道题目给的是一个邻接矩阵。乍一看会觉得跟695 max area of islands是一模一样的,其实不然。695的矩阵展示的是每个1和0的实际位置,而这题则不是。应该说695的矩阵表示某种意义上说已经是无向图的一种表示了,但是这道题目不是。

具体的区别是这样的,这题的核心目标是找一个无向图中的连通分量,而他的每一行或者列代表着一个节点。所以这个矩阵一定是对称且行数等于列数。而对于695来说矩阵每一个位置就代表一个节点。

虽然这两道题表示方法不同,但是解法的本质是一样的。695可以通过将访问过的节点置零的方式来标记已经访问过的节点,而这边用这样的方式会很麻烦。这题的话可以构建一个长度为n的像量,像量每个元素代表一个节点是否被访问过。然后我们遍历所有的n个节点,对于每个节点做DFS或者BFS即可

DFS解法

class Solution:
    def findCircleNum(self, M: List[List[int]]) -> int:
        def dfs(i):
            visited[i] = True
            for j in range(len(M)):
                if M[i][j]==1 and visited[j] == False:
                    dfs(j)
        count = 0
        visited = [False]*len(M)
        for i in range(len(M)):
            if visited[i] == False:
                dfs(i)
                count += 1
        return count

BFS解法

class Solution:
    def findCircleNum(self, M: List[List[int]]) -> int:
        visited = [False]*len(M)
        count = 0
        q = collections.deque()
        for i in range(len(M)):
            if visited[i] == False:
                q.append(i)
                visited[i] = True
                while q:
                    curr = q.popleft()
                    for j in range(len(M)):
                        if M[curr][j] == 1 and visited[j] == False:
                            visited[j] = True
                            q.append(j)
                count+=1
        return count

这里想要提一点就是,虽然BFS和DFS解法的时间复杂度都是O(n*n),但是直观上来讲对于这题应该是DFS更快。实际上run出来的结果也证明了这点,DFS解法超过了95%的提交,而BFS只超过了15%的提交,不过差别这么大也是比较让人惊讶。
还有一个注意的问题是,其实visited[i]=True也可以移到while里面写visited[curr]=True,但是这样其实不合理,在BFS中,visited代表的是是否进过队列,所以一律应该在进队列之后就加入visited

C++版本DFS

class Solution {
public:
    int findCircleNum(vector<vector<int>>& M) {
        vector<bool> visited(M.size(),false);
        int count = 0;
        for (int i=0;i<M.size();++i){
            if (visited[i] == false){
                dfs(M,i,visited);
                ++count;
            }
        }
        return count;
    }
    void dfs(vector<vector<int>>& M,int i, vector<bool>& visited){
        visited[i] = true;
        for (int j=0;j<M.size();++j){
            if (M[i][j]==1 && visited[j]==false){
                dfs(M,j,visited);
            }
        }
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值