Python并查集朋友圈问题的实现

引言

在学习算法和数据结构中,我们经常会遇到并查集这个概念。并查集是一种用于解决集合合并与查询的数据结构,常用于解决图论中的一些问题,比如判断两个节点是否属于同一个连通分量。本文将介绍如何使用Python实现并查集来解决朋友圈问题。

什么是朋友圈问题

朋友圈问题是指给定n个人和m对关系,每对关系表示两个人之间是朋友关系。我们要判断给定的关系是否构成了一个或多个朋友圈。如果两个人直接或间接地通过其他人相互认识,则他们属于同一个朋友圈。朋友圈问题本质上是一个图的连通性问题。

并查集的工作原理

并查集是一种树形结构,用于表示一些不相交的集合。每个节点表示一个元素,树的根节点表示该集合的代表元素。并查集的主要操作包括合并两个集合和查询元素所属的集合。

下面是并查集的一些基本操作:

  1. 初始化:对于n个元素,初始化n个集合,每个元素的父节点指向自己。

  2. 查找:查找元素所属的集合,即找到根节点。

  3. 合并:将两个元素所属的集合合并成一个集合。

朋友圈问题的实现步骤

下面是解决朋友圈问题的实现步骤:

步骤 描述
步骤一 初始化并查集,每个人自成一个集合
步骤二 遍历朋友关系对,将朋友关系中的两个人合并到一个集合中
步骤三 统计并返回最终的朋友圈数量

接下来,我们将一步一步实现这些步骤。

第一步:初始化并查集

并查集可以使用数组来表示,每个元素的父节点即为该元素在数组中的索引。在初始化时,我们将每个人自成一个集合,即将每个人的父节点指向自己。

class UnionFindSet:
    def __init__(self, n: int):
        self.parent = [i for i in range(n)]
        self.count = n

    def find(self, x: int) -> int:
        if self.parent[x] != x:
            self.parent[x] = self.find(self.parent[x])
        return self.parent[x]

    def union(self, x: int, y: int) -> None:
        root_x = self.find(x)
        root_y = self.find(y)
        if root_x != root_y:
            self.parent[root_x] = root_y
            self.count -= 1

在上面的代码中,我们定义了一个UnionFindSet类,其中包含两个核心方法:find和union。find方法用来查找元素所属的集合,union方法用来合并两个集合。

第二步:合并朋友关系

接下来,我们需要遍历朋友关系对,将朋友关系中的两个人合并到一个集合中。

def friend_circles(friendships: List[List[int]]) -> int:
    n = len(friendships)
    union_find_set = UnionFindSet(n)
    for i in range(n):
        for j in range(i + 1, n):
            if friendships[i][j] == 1:
                union_find_set.union(i, j)
    return union_find_set.count

在上面的代码中,我们使用两层循环遍历朋友关系对,如果两个人是朋友关系,则将他们合并到一个集合中。

第三步:统计朋友圈数量

最后,我们需要统计并返回最终的朋友圈数量。

def friend_circles(friendships: List[List[int]]) -> int:
    # 省略初始化并查集和合并朋友关系的代码
    return union_find