挺灵活的一道题,有点绕
分析:每次只能用0交换,有两种情况:
1. 0不在0位,那么0如果在第i位,而第i位本应该是i,就应该把0和i数字所在的位置交换。
2. 如果0在0位,而且整个序列到现在还不是有序的,那就把0和第一个序列没在该在的位置上的数字交换。
用cnt统计不在正确位置上的数字个数
#include<cstdio>
#include<vector>
#include<algorithm>
using namespace std;
int main()
{
int n;
int num,cnt=0,ans=0,index=1;
scanf("%d",&n);
vector<int> v(n);
for(int i=0;i<n;i++)
{
scanf("%d",&num);
v[num]=i;//表示数字num在i号位置上
if(num!=i&&num!=0) cnt++;
}
while(cnt>0)
{
if(v[0]==0)
{
while(index<n)
{
if(v[index]!=index)
{
swap(v[index],v[0]);
ans++;
break;///***
}
index++;
}
}else
{
swap(v[0],v[v[0]]);///***
ans++;
cnt--;
}
}
printf("%d",ans);
return 0;
}
注意:因为多次涉及到想要知道某个数所在的位置,每次都遍历数组太麻烦了,干脆在保存的时候就保存每个数字所在的位置好了,即v[i] = j表示i数字在j位置,所以每次交换i和0只需要交换v[i]和v[0]就好了第二个注意点,很重要,如果不处理会产生两个测试点超时:在0在0位的时候,找寻第一个不在该在的位置的数的时候,如果每次都for循环从头开始找,那么时间复杂度会很高,但是我们知道,找的时候找的是第一个不在该在位置的数,那么index每前进一步都说明前面的数字是符合在该在的位置上的,而且在该在的位置上的数是不可能再交换变化的,所以直接设置一个index的变量,每次找第一个数的时候就可以直接从上一次index开始查找,避免了每次都从头找。