PAT A1067 不懂!

//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;
} 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值