n
对情侣坐在连续排列的2n
个座位上,想要牵到对方的手。人和座位由一个整数数组
row
表示,其中row[i]
是坐在第i
个座位上的人的 ID。情侣们按顺序编号,第一对是(0, 1)
,第二对是(2, 3)
,以此类推,最后一对是(2n-2, 2n-1)
。返回 最少交换座位的次数,以便每对情侣可以并肩坐在一起。 每次交换可选择任意两人,让他们站起来交换座位。
分析:1.拿到题有什么思路?2.为什么可以用并查集?3.如何使用并查集?
针对1:观察题目思考,有哪些性质:2k-1和2k-2应该在一起,和下标i无关。
在移动同学的时候有哪些操作:a的情侣在b的旁边,b的情侣在a的旁边,只需要移动一次即可。假设a的情侣在b旁,b的情侣在c旁,c的情侣在a旁,这时候需要移动2次。
如何判断a的情侣:对于a来说,只需要找到//2商相同的数字即可。
针对2:假设一共有n对情侣,如果每个情侣都能够牵手成功,那么此时的连通块的数目为n,因为这时候不需要移动。当情况为,a的情侣在b旁,b的情侣在a旁,将a和b 并成一个连通块。而其他的情侣都成功牵手,这时候连通块的数量为n-1。需要操作的数量为n-(n-1)。
针对3:看代码.
class Solution:
def minSwapsCouples(self, row: List[int]) -> int:
n = len(row)
m = n//2
fa = list(range(m))
def get(a):
if a != fa[a]:
fa[a] = get(fa[a])
return fa[a]
def union(a,b):
fa[get(a)] = fa[get(b)]
for i in range(0,n,2):
union(row[i]//2,row[i+1]//2)
cnt = sum(1 for i in range(m) if i==get(i))
return m-cnt