【PAT】A1067 Sort with Swap(0, i) (25分)

题目链接

思路与总结:

  • 这一排序方法的核心思想就是每次让一个数回到正确位置:

  • 如样例初始状态{4, 0, 2, 1, 3} 此时数字0在①号位,而①号位本应该是数字1,那么找到数字1,发现它在③号位,故而两数交换位置 得到新数列 即Swap(0, 1) => {4, 1, 2, 0,3};此时数字1在①号位,数字1已归位。这一操作:交换次数cnt+1,并归位一个数。接着重复这一过程。直至所有数字都归位。

  • 但还有一个问题忽略了,那就是当数字0在0号位,如数列{0,1,2,4,3},那岂不是没的换了。此时应找到一个不在本位的数,与0交换,如该例12都在正确位置,而34不在正确位置, 故交换03{3,1,2,4,0}这一操作:交换次数cnt+1,但并没有让某数正确归位。这时0在④号位,故而下一步该04交换,让4回到④号位(这一操作:交换次数cnt+1,并归位一个数)。。。直至全部数字归位。

  • 此题只需设置一个整形数组pos[maxn]pos[i]表示的是数字i在几号位,如样例{4, 0, 2, 1, 3}则初始状态pos[0] = 1, pos[1] = 3, pos[2] = 2, pos[3] = 4, pos[4] = 0;

  • 还需设一个整形变量rest表除了数字0以外还未归位的数,每当归位一个数,rest--,当rest==0,表明n个数全部归位。

  • 还应设置一个整形变量k,可以设初值k=1 (初值为0也没问题)pos[k]==k说明数字k已归位, k作为一个标记标量,用以在当“pos[0] == 0无法进行交换时,寻找一个未归位的数,使得交换继续,交换pos[0]pos[k]”,有了k可以使每次寻找无需从头到尾遍历n个数,而每次只需从k开始向后寻找即可,使得总共寻找的时间复杂度变为O(n)(若不设置k每次遇到0在0号位的情况都取去遍历序列来寻找不在其位的数,会有测试点超时)。

AC代码

#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn = 100010;
int pos[maxn] ;
int rest, n, k=0, cnt = 0;      

int main(){

	scanf("%d",&n);
	int x;
	rest = n-1;
	for(int i=0; i<n; i++){
		scanf("%d",&x);
		pos[x] = i;
        if(x!=0 && pos[x]==x) rest--;

	}

	while(rest>0){
		if(pos[0]!=0){
			swap(pos[0], pos[pos[0]]);
			cnt++;
			rest--;
		}
		else{
			while(pos[k]==k){
				k++;		//从1开始枚举,找到不在本位的数字
			}
			swap(pos[0], pos[k]);
			cnt++;

		}

	}
	printf("%d\n",cnt );
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值