一.原题描述
N couples sit in 2N seats arranged in a row and want to hold hands. We want to know the minimum number of swaps so that every couple is sitting side by side. A swap consists of choosing any two people, then they stand up and switch seats.
The people and seats are represented by an integer from 0
to 2N-1
, the couples are numbered in order, the first couple being (0, 1)
, the second couple being (2, 3)
, and so on with the last couple being (2N-2, 2N-1)
.
The couples’ initial seating is given by row[i]
being the value of the person who is initially sitting in the i-th seat.
Example 1:
Input: row = [0, 2, 1, 3]
Output: 1
Explanation: We only need to swap the second (row[1]) and third (row[2]) person.
Example 2:
Input: row = [3, 2, 0, 1]
Output: 0
Explanation: All couples are already seated side by side.
Note:
len(row)
is even and in the range of[4, 60]
.row
is guaranteed to be a permutation of0...len(row)-1
.
二.中文描述
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
的一个全排列。
三.解题思路
1.此题我们先对数据进行观察,发现每一对情侣对应的数值差值为一,且每对情侣必须相邻,不分前后(即一对情侣0,1的排列也可以是1,0,只要两个人分别在相对应的奇数位与偶数位)
2.为了帮助理解,举出以下例子
第0位 | 第1位 | 第2位 | 第3位 | |
---|---|---|---|---|
人对应编号 | 1 | 0 | 2 | 3 |
人对应编号 | 2 | 3 | 0 | 1 |
上表为满足要求的数据
下面为测试数据
组别 | 第0位 | 第1位 | 第2位 | 第3位 |
---|---|---|---|---|
第一组 | 0 | 2 | 1 | 3 |
第二组 | 3 | 2 | 0 | 1 |
3.接着就是解题了
(1)我们首先固定取偶数位进行判断(当然每组情侣也可以只判断奇数位),以上表测试数据为例,我们只需判断第0位和第2位.
(2)在第一组第0位判断时,我们首先看到为人0,其情侣的值应该为1,第二组第0位判断时,我们看到其为3,对应情侣为2,所以我们可以抽象出以下关系式:
j=cp[i]%2==0?cp[i]+1:cp[i]-1;
其中j
为cp[i]
对应的情侣,当cp[i]
为偶数时,其对应情侣等于cp[i]+1
,当cp[i]
为奇数时,其对应情侣等于cp[i]-1
(3)然后在上述关系式基础上我们进行循环,寻找到cp[i]对应的情侣后交换,此时代码如下:
for(int i=0;i<cp_len;i+=2)
{
int j;
j=cp[i]%2==0?cp[i]+1:cp[i]-1;
if(cp[i+1]!=j)
{
count0++;
for(int m=i+2;m<cp_len;m++)
{
if(cp[m]==j)//找到j了
{
swap(cp[m],cp[i+1]);//交换
break;
}
}
}
}
i为我们检测的偶数位,j为cp[i]对应的情侣值,当cp[i+1]!=j时,我们从i+2位开始寻找j,找到后交换,重复此循环即可得到正确答案。
(4)完整源码如下:
#include<iostream>
using namespace std;
class couple{
public:
int match_couple(int* cp,int lenth)
{
count0=0;
cp_len=lenth;
for(int i=0;i<cp_len;i+=2)
{
int j;
j=cp[i]%2==0?cp[i]+1:cp[i]-1;
if(cp[i+1]!=j)
{
count0++;
// cout<<count0<<endl;
for(int m=i+2;m<cp_len;m++)
{
if(cp[m]==j)
{
swap(cp[m],cp[i+1]);
break;
}
}
}
}
return count0;
}
private:
int count0;
int cp_len;
};
void swap(int* a,int* b)
{
*a=*a+*b;
*b=*a-*b;
*a=*a-*b;
}
int main()
{
couple couples;
int a[]={0,2,1,3},lenth=0,swap_count=0;
lenth=sizeof(a)/sizeof(a[0]);
swap_count=couples.match_couple(a,lenth);
cout<<swap_count;
return 0;
}