题目描述
n
对情侣坐在连续排列的 ```2n ``个座位上,想要牵到对方的手。
人和座位由一个整数数组 row
表示,其中 row[i]
是坐在第 i 个座位上的人的 ID
。情侣们按顺序编号,第一对是 (0, 1)
,第二对是 (2, 3)
,以此类推,最后一对是 (2n-2, 2n-1)
。
返回 最少交换座位的次数,以便每对情侣可以并肩坐在一起。 每次交换可选择任意两人,让他们站起来交换座位。
做题情况
- 做出来且思路与标答一致
- 做出来但思路较为复杂
- 有思路,但时间复杂度较高无法通过
- 没有思路 ☑
自己的想法:
怎么说呢,感觉有点畏难情绪。但其实有一些思路的已经。首先是那种不用换位置就已经是情侣连坐的,我们就不需要考虑了。
对于其他情况,对于两对相邻位置的四个人,如果交换一下,就可以使两对情侣都相邻了。
但对于其他的情况,显然是要绕一个大圈来换。
自己的疑惑,或者说没有绕过来的地方是:如果存在一个圈,那么是否存在更小的圈,使得最终交换的次数更少呢。
于是就卡在这里了。
标答:并查集
实际上,自己已经想了很大部分了。剩下的就是证明不存在更小的圈,以及编写程序了。
对于前者,因为显然当前这对相邻的两个人都在圈里面。因此我们可以根据他们的情侣逐步向两边展开。需要注意的是,这个展开是固定的,因为我们相邻的人是固定的,情侣是固定的,一定是相邻情侣这样交替展开的。所以到了最后形成的圈一定是固定的,也就不存在存在更小的圈的情况了。
至于编写程序,我们就循环进行这个展开过程,以及用集合来表示剩下的点就可以了。
实际代码
class Solution {
public:
int neighbor_man(const int man, vector<int>& row, vector<int>& pos)
{
int neighbor;
if (pos[man] % 2 == 0) return row[pos[man] + 1];
else return row[pos[man] - 1];
}
int wife_man(const int man, vector<int>& row, vector<int>& pos)
{
int wife;
if (man % 2 == 0) return man + 1;
else return man - 1;
}
int minSwapsCouples(vector<int>& row)
{
//想明白了,其实两者是一样的
//还有一个点是不需要想是否有更小的圈导致更少的交换次数,因为当前的两个人一定都在这个圈里,然后向两边扩展,最终得到的圈是唯一的
int n = row.size();
vector<int> pos(n);
unordered_set<int> un_set;
int res = 0;
for (int i = 0; i < n; i += 2)
{
pos[row[i]] = i;
pos[row[i + 1]] = i + 1;
if (row[i] % 2 == 0)
{
if (row[i + 1] != row[i] + 1)
{
un_set.insert(row[i]);
un_set.insert(row[i + 1]);
res++;
}
}
else
{
if (row[i + 1] != row[i] - 1)
{
un_set.insert(row[i]);
un_set.insert(row[i + 1]);
res++;
}
}
}
while (!un_set.empty())
{
auto it = un_set.begin();
int man = *it;
int woman = wife_man(man, row, pos);
un_set.erase(man);
un_set.erase(woman);
while (1)
{
int neighbor = neighbor_man(man,row,pos);
int woman_neighbor = wife_man(neighbor, row, pos);
un_set.erase(neighbor);
un_set.erase(woman_neighbor);
if (neighbor_man(woman_neighbor, row, pos) == woman)
{
res--;
break;
}
else man = woman_neighbor;
}
}
return res;
}
};
总结
其实很多题都是一个思路,不需要把他要强安上什么算法,什么数据结构的。根据这么多刷题的经验,对于题目应该用什么样的大体方法来解决,都有一个比较清晰的概念了,所以就直接去想,遇到问题也多坚持一下就好了。
刷题的进步还是很明显的,最起码这种感觉不会骗人。但是有一个隐患,就是自己不怎么在意自己算法的速度,这点还是要注意一下的。