//ac,勉强理解,还未完全自己实现
//swap(pos[0],pos[pos[0]]);不太懂
/*使用int型变量left记录除零以外的不在本位的数的个数
while(left>0){
if(0在0号位上){
找一个不在本位的数,令其与0交换
交换次数++
}
while(0不在0号位上){
将0所在位置的数与0交换
交换次数++
left--;
}
} */
//我只能说一句,换个马甲,我真的看不懂!但是这是暂时的,我将各个击破
//注意回到本位的不要再动
//注意设全局,当前不在本位的最小数,来控制复杂度在线性以内
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn=100010;
int pos[maxn];//存放各数字当前所处的位置编号
int main(){
int n,ans=0;//ans表示交换的总次数
scanf("%d",&n);
int left=n-1,num;//left存放除0以外的不在本位上的数的个数
for(int i=0;i<n;i++){
scanf("%d",&num);
pos[num]=i;//num所处的位置为i。我靠好绕
if(num==i&&num!=0){
left--;//令left减1
}
}
int k=1;//k存放除0以外当前不在本位上的最小的数
while(left>0){//只要还有数不在本位上。每次循环都要检查0是否在本位上,将作出不同的操作
if(pos[0]==0){//如果0在本位上,则寻找一最小的不在本位上的数交换
while(k<n){//还有没回到本位的
if(pos[k]!=k){//找到一个当前不在本位上的数k 。如果在本位就跳过这里,k加1看是否在本位
swap(pos[0],pos[k]);//将k与0位置交换
ans++;//交换次数加1
break; //退出本次循环,也就相当于执行完if(pos[0]==0)的条件句
}
k++;//判断k+1是否在本位
}//直到找到一个不在本位并且最小的数
}
//只要0不在本位,就将0所在位置的数的当前所处位置与0的位置交换。这句话是对的,理解了你就懂了
while(pos[0]!=0){
swap(pos[0],pos[pos[0]]);//将0余pos[0]交换
ans++;//交换次数加1
left--; //不在本位上的数的个数减1
}
}
printf("%d\n",ans);//输出结果
return 0;
}
看看我自己写的挫代码吧
//错了,这题,这题还蛮难的
//这题我花了10分钟以内明白了大意是除了0以外有多少数字不在应该在的位置上。
//看书上说涉及到贪心。我想它因为只能和0换,怎么样换最少都应该是上一行描述的那样
#include<cstdio>
#include<algorithm>
//#define LOCAL
using namespace std;
const int maxn=100010;
int a[maxn];
int main(){
#ifdef LOCAL
freopen("A1067data.in","r",stdin);
freopen("A1067data.out","w",stdout);
#endif
int n;
scanf("%d",&n);
for(int i=0;i<n;i++){
scanf("%d",&a[i]);
}
//sort(a,a+n);
int count=0;
for(int i=0;i<n;i++){
if(a[i]!=i)
count++;
}
printf("%d\n",count);
return 0;
}