思路与总结:
-
这一排序方法的核心思想就是每次让一个数回到正确位置:
-
如样例初始状态
{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交换,如该例1与2都在正确位置,而3与4不在正确位置, 故交换0和3得{3,1,2,4,0}。这一操作:交换次数cnt+1,但并没有让某数正确归位。这时0在④号位,故而下一步该0与4交换,让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号位的情形,通过引入额外变量k提高算法效率。
228

被折叠的 条评论
为什么被折叠?



