题目给定一个序列0,1,……,N-1,要求通过两两交换(0和另一个数),使其变为递增序列
题目意思很简单,问题是如何用尽可能最简单的策略来实现。
1.若0在i号位(i≠0),则找到i所在位置,将0与i交换
2.若0在0号位,则找到第一个不在自己位置的数,将0与其交换,这样又回到了1所在的情况,也不会对已经到达自己位置的数字产生影响
以下为算法笔记中的模拟过程和参考代码:
另外,注意代码中的left变量
#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn=100010;
int pos[maxn];
int main(){
int n,ans = 0;
scanf("%d", &n);
int left=n-1,num;//left存放除0以外不在本位上的数
for(int i=0; i<n; i++){
scanf("%d", &num);
pos[num] = i;
if(num==i&&num!=0)//去除已经在本位上的数
left--;
}
int k=1;//除0以外不在本位上最小的数
while(left>0){
if(pos[0] == 0){//0在本位上,寻找第一个当前不在本位上的数与0交换
while(k<n){
if(pos[k] != k){
swap(pos[0], pos[k]);
ans++;
break;
}
k++;
}
}
while(pos[0] != 0){//0不在本位上,寻找应在0位置上的数字与0交换
swap(pos[0], pos[pos[0]]);
ans++;
left--;
}
}
printf("%d\n", ans);
return 0;
}