题目链接:https://pintia.cn/problem-sets/994805342720868352/problems/994805403651522560
题目大意:给定n个数的序列(0--n-1),每次执行swap(0, *)操作,意思是把某个数所在的位置跟0所在的位置交换,求最少的移动次数。
分析:设一个left表示除0以外,还有多少个数不在自己的位置上,如果0的位置为0,那么就随便找一个不在自己位置上的数,与0交换;如果0不在位置0,那么执行swap(pos[0], pos[pos[0]]),且left--。
值得注意的是,如果是第一种情况,那么我们需要找一个不在自己位置上的数,所以可以从1按顺序开始找,但这个下标初始化在循环的外面,因为是按从小到大的顺序来的,假设当前k==x,那么1--x-1肯定已经回到自己的位置了,所以不用每次都从头开始找。
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 5;
int pos[N];
int main() {
int n, x, sum = 0;
scanf("%d", &n);
int left = n - 1;
for(int i = 0; i < n; i++) {
scanf("%d", &x);
pos[x] = i;
if(x == i && x != 0) left--;
}
int k = 1;
while(left > 0) {
if(pos[0] == 0) {
while(k < n) {
if(pos[k] != k) {
swap(pos[0], pos[k]);
sum++;
break;
}
k++;
}
}
while(pos[0] != 0) {
swap(pos[0], pos[pos[0]]);
sum++;
left--;
}
}
printf("%d\n", sum);
return 0;
}