目录
765. 情侣牵手
难度困难199
N 对情侣坐在连续排列的 2N 个座位上,想要牵到对方的手。 计算最少交换座位的次数,以便每对情侣可以并肩坐在一起。 一次交换可选择任意两人,让他们站起来交换座位。
人和座位用 0
到 2N-1
的整数表示,情侣们按顺序编号,第一对是 (0, 1)
,第二对是 (2, 3)
,以此类推,最后一对是 (2N-2, 2N-1)
。
这些情侣的初始座位 row[i]
是由最初始坐在第 i 个座位上的人决定的。
示例 1:
输入: row = [0, 2, 1, 3] 输出: 1 解释: 我们只需要交换row[1]和row[2]的位置即可。
示例 2:
输入: row = [3, 2, 0, 1] 输出: 0 解释: 无需交换座位,所有的情侣都已经可以手牵手了。
说明:
len(row)
是偶数且数值在[4, 60]
范围内。- 可以保证
row
是序列0...len(row)-1
的一个全排列。
方法一 并查集
思路
自己想到了并查集,但是没有很好的联系到题目,还是参考别人的题解理解的。
节点是情侣对数的编号,遍历每对位置上
首先,我们总是以「情侣对」为单位进行设想:
对于每对相邻的位置,如果是第 i 对与第 j 对坐在了一起,则在 i 号节点与 j 号节点之间连接一条边,代表需要交换这两对情侣的位置。
当有两对情侣相互坐错了位置,ta们两对之间形成了一个环。需要进行一次交换,使得每队情侣独立(相互牵手)
如果三对情侣相互坐错了位置,ta们三对之间形成了一个环,需要进行两次交换,使得每队情侣独立(相互牵手)
如果四对情侣相互坐错了位置,ta们四对之间形成了一个环,需要进行三次交换,使得每队情侣独立(相互牵手)
也就是说,如果我们有 k 对情侣形成了错误环,需要交换 k - 1 次才能让情侣牵手。
作者:AC_OIer
链接:https://leetcode-cn.com/problems/couples-holding-hands/solution/liang-chong-100-de-jie-fa-bing-cha-ji-ta-26a6/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
假设形成cnt个环,环的节点数分别为 {k1,k2...}
,
则 ans=k1-1 + k2-1 + ...kcnt-1 = (k1+k2+...)-cnt=m-cnt
代码
参考官方的思路 直接加的k1-1 + k2-1 + ...kcnt-1
class Solution {
public:
vector<int> fa;
int findRoot(int x){
if(fa[x]==-1)
return x;
int tmp=findRoot(fa[x]);
fa[x]=tmp;
return tmp;
}
void add(int x,int y){
x=findRoot(x);
y=findRoot(y);
if(x!=y){
fa[x]=y;
}
}
int minSwapsCouples(vector<int>& row) {
//并查集
int n=row.size()/2; //情侣的对数
fa=vector<int>(n,-1);//初始化为-1
for(int i=0;i<row.size();i+=2){
int a=row[i]/2;
int b=row[i+1]/2;
add(a,b);
}
map<int,int> rootcount;
for(int i=0;i<n;i++){
int t=findRoot(i);
rootcount[t]++; //统计了每个环的父节点 每个环的结点数
}
int ans=0;
for(auto it=rootcount.begin();it!=rootcount.end();it++){
ans+=(it->second-1); //累加k-1
}
return ans;
}
};
修改后的题解,不需要统计每个环父节点:
class Solution {
public:
vector<int> fa;
int findRoot(int x){
if(fa[x]==-1)
return x;
int tmp=findRoot(fa[x]); //没有写fa[x]
fa[x]=tmp;
return tmp;
}
void add(int x,int y){
x=findRoot(x);
y=findRoot(y);
if(x!=y){
fa[x]=y;
}
}
int minSwapsCouples(vector<int>& row) {
//并查集
int n=row.size()/2; //情侣的对数
fa=vector<int>(n,-1);//初始化为-1
for(int i=0;i<row.size();i+=2){ //i的最值是row.size
int a=row[i]/2;
int b=row[i+1]/2;
add(a,b);
}
int count=0;
for(int i=0;i<n;i++){
if(fa[i]==-1)
count++;
}
return n-count;
}
};