并查集数据结构
- 并查集是一种数据结构,并(Union)代表合并,查(Find)代表查找,集(Set)代表这是一个以字典为基础的数据结构,基本功能是合并集合中的元素,查找集合中的元素。
- 并查集的典型应用是有关连通分量的问题,并查集解决单个问题(添加,合并,查找)的时间复杂度都是O(1)。
数据结构
在并查集里面,每个节点会记录它的父节点
class UnionFind:
def __init__(self):
# 记录每个节点的父节点
self.father = {}
如果节点互相连通(从一个节点可以达到另一个节点),那么他们的祖先是相同的。
初始化
当把一个新节点添加到并查集中,它的父节点应该为空。
def add(self,x):
"""
添加新节点
"""
if x not in self.father:
self.father[x] = None
合并两个节点
如果两个节点是连通的,那么就要把他们合并,也就是他们的祖先是相同的。
def merge(self, x, y):
# 合并两个节点
root_x, root_y = self.find(x), self.find(y)
if root_x != root_y:
self.father[root_x] = root_y
两个节点是否连通
判断两个节点是否处于同一个连通分量的时候,就要判断他们的祖先是否相同。
def is_connected(self,x,y):
return self.find(x) == self.find(y)
查找祖先
如果节点的父节点不为空,那就不断迭代。
def find(self,x):
# 查找根节点
root = x
while self.father[root] != None:
root = self.father[root]
return root
class UnionFind:
def __init__(self):
self.father = {}
# 额外记录集合的数量
self.num_of_sets = 0
def find(self,x):
root = x
while self.father[root] != None:
root = self.father[root]
while x != root:
original_father = self.father[x]
self.father[x] = root
x = original_father
return root
def merge(self,x,y):
root_x,root_y = self.find(x),self.find(y)
if root_x != root_y:
self.father[root_x] = root_y
# 集合的数量-1
self.num_of_sets -= 1
def add(self,x):
if x not in self.father:
self.father[x] = None
# 集合的数量+1
self.num_of_sets += 1
class Solution:
def findCircleNum(self, M: List[List[int]]) -> int:
uf = UnionFind()
for i in range(len(M)):
uf.add(i)
for j in range(i):
if M[i][j]:
uf.merge(i,j)
return uf.num_of_sets
数组存储
class UnionFind:
"""并查集"""
def __init__(self, n):
self.parent = [i for i in range(n)]
# 初始连通分量数为 n 个
self.count = n
def find(self, x):
if x != self.parent[x]:
self.parent[x] = self.find(self.parent[x])
return self.parent[x]
def union(self, u, v):
u_root = self.find(u)
v_root = self.find(v)
# 合并,连通分量数减少
if u_root != v_root:
self.parent[u_root] = v_root
self.count -= 1
class Solution:
def findCircleNum(self, isConnected: List[List[int]]) -> int:
n = len(isConnected)
uf = UnionFind(n)
for i in range(n):
for j in range(i, n):
if isConnected[i][j] == 1:
uf.union(i, j)
return uf.count