题目
Given any permutation of the numbers {0, 1, 2,…, N−1}, it is easy to sort them in increasing order. But what if Swap(0, *) is the ONLY operation that is allowed to use? For example, to sort {4, 0, 2, 1, 3} we may apply the swap operations in the following way:
Swap(0, 1) => {4, 1, 2, 0, 3}
Swap(0, 3) => {4, 1, 2, 3, 0}
Swap(0, 4) => {0, 1, 2, 3, 4}
Now you are asked to find the minimum number of swaps need to sort the given permutation of the first N nonnegative integers.
Input Specification:
Each input file contains one test case, which gives a positive N (≤10
5) followed by a permutation sequence of {0, 1, …, N−1}. All the numbers in a line are separated by a space.
Output Specification:
For each case, simply print in a line the minimum number of swaps need to sort the given permutation.
Sample Input:
10
3 5 7 2 6 4 9 0 8 1
Sample Output:
9
题目大意
给定一序列,只能用0和别的数字交换位置,要使序列有序,最少需要交换几次。
直觉
每次找出0号位置上应该存在的数字,与其交换,但是会出现0提早到了0号位,循环不能执行下去的情况,可以加一个判断,如果此时还无序,找到最小的数字,先与0交换,再继续。
问题是没法证明这种方法是次数最少的方法
先做做看,是不是正确的方法。
解题思路
提交后A了,说明直觉上的思路是可行的,只是数学上没有证明这是次数最少的一种交换方法。
复杂度分析
O(n²),n是输入数组的规模。
代码
#include<iostream>
#include<cstdio>
using namespace std;
bool judge(int a[],int n){
bool flag=1;
for(int i=0;i<n;++i){
if(a[i]!=i)flag=0;
}
return flag;
}
void swap(int a[],int n){
int temp=0;
for(int i=0;i<n;++i){
if(a[i]==0){
temp=i;
}
}
for(int j=0;j<n;++j){
if(a[j]==temp){
a[j]=0;
a[temp]=temp;
}
}
}
int main(){
int total;
scanf("%d",&total);
int group[total];
for(int i=0;i<total;++i)scanf("%d",&group[i]);
int step=0;//记录交换次数
bool flag=0;//判断序列是否有序
flag=judge(group,total);
while(!flag){
if(group[0]==0){
for(int i=1;i<total;++i){
if(group[i]!=i){
group[0]=group[i];
group[i]=0;
++step;
break;
}
}
}
swap(group,total);
flag=judge(group,total);
++step;
}
printf("%d",step);
}