一. 回溯法
1. 回溯法比较容易理解,如果我们每次都能让至少1对情侣坐在一起,那么最终肯定能使所有情侣都坐在一起,但是(x,y)如果而这不是情侣,可以找到x的情侣x1,或者y的情侣y1,但是需要比较二者哪个次数更小。
2. 首先变为【0,0,1,1】模式,这样只要比较数值是否相同即可找到情侣。
3.回溯,首先判断第p个是不是情侣,如果x==y,是情侣,直接处理下一种情况。
4. 如果不是,在p后面找情侣,因为p前面已经处理好了是情侣,分两种情况,找到x情侣,以及找到y情侣,分别交换,并最终看哪个次数最小,返回。
5. 很遗憾,思路对的,超时了。
class Solution {
public:
void swap(vector<vector<int>>& pairs, int a, int b,int c,int d) {
int t = pairs[a][b];
pairs[a][b] = pairs[c][d];
pairs[c][d] = t;
}
int nums(vector<vector<int>>& pairs, int p, int n) {
if(p==n) return 0;
int x = pairs[p][0], y = pairs[p][1];
if(x==y) return nums(pairs, p+1, n);
int first_x = 0, first_y = 0, second_x = 0,second_y = 0;
for(int i=p+1;i<n;i++) {
for(int k=0;k<=1;k++) {
if(pairs[i][k]==x) {first_x=i, first_y=k;}
if(pairs[i][k]==y) {second_x=i, second_y=k;}
}
}
swap(pairs, p,1,first_x,first_y);
int ans1 = 1+nums(pairs, p+1, n);
swap(pairs, p,1,first_x,first_y);
swap(pairs, p,0,second_x,second_y);
int ans2 = 1+nums(pairs, p+1, n);
swap(pairs, p,0,second_x,second_y);
return min(ans1,ans2);
}
int minSwapsCouples(vector<int>& row) {
int n_2 = row.size();
int n = n_2/2;
vector<vector<int>> pairs(n, vector<int>(2,0));
for(int i=0;i<n;i++) {
pairs[i][0] = row[2*i]/2;
pairs[i][1] = row[2*i+1]/2;
}
return nums(pairs,0,n);
}
};
二. 直接贪心,每次把不是情侣的换成情侣
1. 如果一个人的编号为 x
,那么他的情侣的编号为 x ^ 1
, ^
在这里是异或操作。这个仔细思考一下是对的。
2. 异或优先级小,要加括号。
class Solution {
public:
int minSwapsCouples(vector<int>& row) {
int n_2 = row.size();
int ans = 0;
for(int i=0;i<n_2-1;i+=2) {
int x = row[i];
if(x==(row[i+1]^1)) continue;
for(int j=i+2;j<n_2;j++) {
if(x==(row[j]^1)) {
swap(row[i+1], row[j]);
ans += 1;
break;
}
}
}
return ans;
}
};