放两个模板
模版一:
初始化状态下,每个节点都不在子集合里,根节点的parent是None
class UnionFind:
def __init__(self):
"""
记录每个节点的父节点
"""
self.father = {}
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,val):
"""
合并两个节点
"""
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 add(self,x):
"""
添加新节点
"""
if x not in self.father:
self.father[x] = None
模板二:
初始状态下所有节点的parent是他自己,所有没有了add函数,而且在find root函数里判断条件不是parent为None,而是parent为自身
1202. 交换字符串中的元素
class UnionFind:
def __init__(self,n):
self.parent = [i for i in range(n)]
def find(self, x):
root = x
while self.parent[root]!=root:
root = self.parent[root]
while x!=root:
self.parent[x],x, = root ,self.parent[x]
return root
def union(self,x,y):
root_x, root_y = self.find(x), self.find(y)
if root_x!=root_y:
self.parent[root_x]=root_y
from collections import defaultdict
class Solution:
def smallestStringWithSwaps(self, s: str, pairs: List[List[int]]) -> str:
uf = UnionFind(len(s))
for i,j in pairs:
uf.union(i,j)
children = defaultdict(lambda: set())
for i,j in pairs:
root = children[uf.find(i)]
root.add(i)
root.add(j)
arr = list(s)
for v in children.values():
for i,j in zip(sorted(v),sorted([arr[i] for i in v])):
arr[i]=j
return "".join(arr)
200. 岛屿数量
https://leetcode-cn.com/problems/number-of-islands/
岛屿的数量还是用DFS写起来好理解一些
1319. 连通网络的操作次数
https://leetcode-cn.com/problems/number-of-operations-to-make-network-connected/
- n台计算机至少需要n-1条线才能全部联通
- 用并查集计算有多少个cluster,那么至少需要cluster-1条多余的连接线才可以做到全连通
如何计算多余的线? 其实并不需要计算,因为如果两个cluster之间没有足够的线把他们链接起来,那么就已经不满足第一个条件了
class UnionFind:
def __init__(self, n):
self.family = [i for i in range(n)]
self.redundant = 0
def find(self,x):
root = x
while self.family[root]!=root:
root = self.family[root]
while root!=x:
self.family[x], x = root, self.family[x]
return root
def union(self,x,y):
root_x, root_y = self.find(x), self.find(y)
if root_x!=root_y:
self.family[root_x] = root_y
def is_connected(self,x,y):
return self.find(x) == self.find(y)
class Solution:
def makeConnected(self, n: int, connections: List[List[int]]) -> int:
if len(connections) < n-1:
return -1
uf = UnionFind(n)
for a,b in connections:
if uf.is_connected(a,b):
uf.redundant+=1
uf.union(a, b)
clusters = 0
for i in range(n):
if uf.family[i]==i:
clusters+=1
if uf.redundant < clusters-1:
return -1
else:
return clusters-1