此题解采用了并查集的数据结构来解决情侣牵手的问题。首先创建一个UnionSet类来处理并查集相关的操作,包括初始化、查找和合并。题目中的每对情侣编号为(0,1), (2,3)等,意味着两个人的ID除以2的结果如果相同,则它们是一对。算法的核心在于将每对坐在一起的情侣通过union操作合并在同一个集合中。每次合并减少一个集合,初始集合数为n对情侣即n/2。最后,需要的交换次数为初始集合数减去最后的集合数,即n/2 - uset.set。
时间复杂度: O(n)
空间复杂度: O(n)
class Solution:
def minSwapsCouples(self, row: List[int]) -> int:
class UnionSet:
def __init__(self, n = 100000):
self.father: list = list(range(n)) # 每个元素的父节点初始指向自己
self.size: list = [1] * n # 初始化每个集合的大小为1
self.stack = [] # 辅助栈,用于路径压缩
self.set = n # 记录并查集中集合的数量
def find(self, i):
while i != self.father[i]: # 查找根节点
self.stack.append(i)
i = self.father[i]
while self.stack: # 路径压缩
self.father[self.stack.pop()] = i
return i
def union(self, x, y):
fx = self.find(x)
fy = self.find(y)
if fx != fy: # 合并两个集合
self.set -= 1
if self.size[fx] >= self.size[fy]: # 按秩合并
self.size[fx] += self.size[fy]
self.size[fy] = None
self.father[fy] = fx
else:
self.size[fy] += self.size[fx]
self.size[fx] = None
self.father[fx] = fy
n = len(row)
npair = n // 2
uset = UnionSet(npair)
for i in range(0, n, 2):
uset.union(row[i]//2, row[i+1]//2) # 将每对坐在一起的情侣合并为一个集合
return npair - uset.set # 返回需要的最小交换次数