Python并查集朋友圈问题的实现
引言
在学习算法和数据结构中,我们经常会遇到并查集这个概念。并查集是一种用于解决集合合并与查询的数据结构,常用于解决图论中的一些问题,比如判断两个节点是否属于同一个连通分量。本文将介绍如何使用Python实现并查集来解决朋友圈问题。
什么是朋友圈问题
朋友圈问题是指给定n个人和m对关系,每对关系表示两个人之间是朋友关系。我们要判断给定的关系是否构成了一个或多个朋友圈。如果两个人直接或间接地通过其他人相互认识,则他们属于同一个朋友圈。朋友圈问题本质上是一个图的连通性问题。
并查集的工作原理
并查集是一种树形结构,用于表示一些不相交的集合。每个节点表示一个元素,树的根节点表示该集合的代表元素。并查集的主要操作包括合并两个集合和查询元素所属的集合。
下面是并查集的一些基本操作:
-
初始化:对于n个元素,初始化n个集合,每个元素的父节点指向自己。
-
查找:查找元素所属的集合,即找到根节点。
-
合并:将两个元素所属的集合合并成一个集合。
朋友圈问题的实现步骤
下面是解决朋友圈问题的实现步骤:
步骤 | 描述 |
---|---|
步骤一 | 初始化并查集,每个人自成一个集合 |
步骤二 | 遍历朋友关系对,将朋友关系中的两个人合并到一个集合中 |
步骤三 | 统计并返回最终的朋友圈数量 |
接下来,我们将一步一步实现这些步骤。
第一步:初始化并查集
并查集可以使用数组来表示,每个元素的父节点即为该元素在数组中的索引。在初始化时,我们将每个人自成一个集合,即将每个人的父节点指向自己。
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