ps:此题需要注意的点就是 题目中交换的是数字 但是在实际交换中 交换的为坐标
思路如下:
将所有的数按照它们在未排序的序列中的位置进行编号,即 p[i] 表示数字 i 在输入序列中的位置,然后我们按照顺序处理每个位置上的数字。
如果当前位置上的数字不是 i,那么我们就交换 p[0] 和 p[i],这样就能将 i 移动到它应该在的位置。
需要注意的是,我们在处理每个位置上的数字时,先处理掉 0 所在的环,这样可以避免在之后的操作中与 0 所在的环交叉而导致死循环。
时间复杂度
最坏情况下,每个数都需要向后扫描一遍,因此总时间复杂度为 O(n^2)。但是因为每个数最多只会被交换一次,因此实际上运行时间会远远快于 O(n^2)。
贴一下ac代码:
#include<iostream>
using namespace std;
const int N=100010;
int p[N];
int main()
{
int n,res=0;
cin>>n;
for(int i=0;i<n;++i)
{
int x;
cin>>x;
p[x]=i;//x元素在位置i
}
for(int i=0;i<n;++i)
{
while(p[0]) swap(p[0],p[p[0]]),res++;//先处理完0所在的环,把0所在环的其他元素交换到他应有的位置上
if(p[i]!=i) swap(p[0],p[i]),res++;//在将除0以外的其他环进行合并
}
cout<<res;
return 0;
}