题目描述
给定一个数列 a,这个数列满足 ai!=aj,现在要求你把这个数列从小到大排序,每次允许你交换其中任意一对数,请问最少需要几次交换?
输入格式
第一行是一个整数,代表数字个数 n。
第二行有 n 个整数用空格分隔开,表示数列 a。
输出格式
只有一行,包含一个数,表示最少的交换次数。
输入输出样例
输入 #1
8 8 23 4 16 77 -5 53 100输出 #1
5说明/提示
数据规模与约定
对于 100%100% 的数据,保证 1≤n≤105,−231<ai<231−1。
分析:
开始直接套用快排模板直接计算结果只过了1个数据,后来参考资料发现直接用map进行模拟就能AC。
第一次错误代码:
#include <iostream>
#include <cstdio>
using namespace std;
const int N=1e5+10;
int a[N];
int ans;
void quick_sort(int q[],int l,int r)
{
if(l>=r) return ;
int x=q[l+r >> 1];
int i=l-1;
int j=r+1;
while(i<j)
{
do i++; while(q[i]<x);
do j--; while(q[j]>x);
if(i<j)
{
swap(q[i],q[j]);
ans++;
}
}
quick_sort(q,l,j);
quick_sort(q,j+1,r);
}
int main()
{
int n;
scanf("%d",&n);
for(int i=0;i<n;i++) scanf("%d",&a[i]);
quick_sort(a,0,n-1);
printf("%d",ans);
return 0;
}
AC代码:
#include <iostream>
#include <cstdio>
#include <map>
#include <algorithm>
using namespace std;
const int N=1e5+10;
int a[N];
int b[N];
int ans;
map<int,int> m;
int main()
{
int n;
scanf("%d",&n);
for(int i=0;i<n;i++)
{
scanf("%d",&a[i]);
m[a[i]]=i;
b[i]=a[i];
}
sort(b,b+n);
for(int i=0;i<n;i++)
{
if(a[i]!=b[i])
{
int t=m[b[i]];
swap(a[i],a[t]);
ans++;
m[a[i]]=i;
m[a[t]]=t;
}
}
printf("%d",ans);
return 0;
}