leetcode547朋友圈(并查集)

这是我和yzc大佬在数据结构课上写的题,我:并查集我一点概念都没有。 yzc大佬:你做做试试。
然后我就开了这道题。我写了十分钟,妈的这个并查集怎么写,感觉只会DFS。然后yzc大佬接手,五分钟后,AC。然后我盯着他的代码看了半天没看懂。
下课后,丫的突然开窍,好简单,我可以!
题目是这样的

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

然后并查集也有两种思路,一种复杂度是恒为O(N)O(N)O(N),另一种复杂度是O(1)−O(logN)O(1)-O(logN)O(1)O(logN),我两种都是实现了一下。
先说一下我的并查集解题思路,并查集是这样的,先寻找有关系的两个对象,每找到一组关系,然后查找两个对象分别属于的集合,若不是同一个集合,那么就合并两个集合。以此迭代。

  1. 线性并查集,代码如下
class Solution(object):
    def findCircleNum(self, M):
        """
        :type M: List[List[int]]
        :rtype: int
        """
        #构造初始并查集
        li = [i for i in range(len(M))]
        for j in range(len(M)):
            for k in range(len(M)):
                if M[j][k] == 1 and j != k:
                #这里是寻找到了有关系的两个对象,然后开始将其中一个集合的下标的值都改成另一个集合下标的值
                    for num in range(len(li)):
                        if li[num] == min(li[j],li[k]):
                            li[num] = max(li[j],li[k])    
        return len(set(li))
  1. 非线性并查集
class Solution(object):
    def __init__(self):
        self.li = [i for i in range(205)]
    def findCircleNum(self, M):
        """
        :type M: List[List[int]]
        :rtype: int
        """
        for i in range(len(M)):
            for j in range(len(M)):
                if M[i][j] == 1 and i != j:
                    self.merge(i, j)
    
    def merge(self, i, j):
        fi = self.find(i)
        fj = self.find(j)
        if fi != fj:
            self.li[fi] = self.li[fj]

    def find(self, x):
        while self.li[x] != x:
            x = self.li[x]
        return x

这里重点写一下非线性并查集

  1. 首先我们创建初始并查集
朋友圈0123
下标0123
  1. 然后我们开始寻找有关系的两个同学
  2. 找到两个同学有关系(M[i][j]=1 and i != j)后,我们开始需要开始合并这两个朋友圈merge(),再合并朋友圈是,我们需要找到这两个朋友圈分别是几号朋友圈,这里就用到的定义的find()函数,我们使用递归的方法得到根节点(也就是他们的朋友圈序号),然后对比他们得到的朋友圈序号,将其中一个的序号进行修改。
  3. 最后查找我们的得到的并查集序列,查找在人数范围内总共有几个朋友圈。(查找li[i] == i的数量)。
    这就是效率较高的并查集的做法。

转载于:https://www.cnblogs.com/yfc0818/p/11072610.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值