题目描述
分析
(1)由于0只是每次交换的一个基准,因此0所在的位置错误可以不计入总的错误数,因为最终其他的数都排列好之后,0必然也在0号位。由于一次交换时0回到0号位而需要将错误数减少2,而不回到0号位只需要减1,这样做是为了避免分类。
(2)为了方便找到每个数字所在的位置,可用v[i]
存放数字i
所在的位置。每次只需要对v[]
进行swap即可。
(3)当0回到0号位而并未完成工作时,需要找一个放在错误位置的数与0交换,所以可以事先存好错误的数。
#include<iostream>
#include<cstring>
#include<string>
#include<vector>
#include<map>
#include<set>
#include<unordered_map>
#include<unordered_set>
#include<stack>
#include<queue>
#include<cmath>
#include<algorithm>
using namespace std;
int v[100005];
unordered_set<int> sett;
int main() {
#ifdef ONLINE_JUDGE
#else
freopen("1.txt", "r", stdin);
#endif
int n, cnt=0; cin >> n;
for (int i = 0; i < n; i++) {
int num; cin >> num;
v[num] = i;
if (num != 0 && num != i) sett.insert(num);
}
while (sett.size() > 0) {
if (v[0] == 0) {
swap(v[0], v[*sett.begin()]);
cnt++;
}
else {
sett.erase(v[0]); //注意先erase,因为swap会改变v[0]的值
swap(v[v[0]], v[0]);
cnt++;
}
}
cout << cnt;
return 0;
}