题目描述:
给定一个数列{an},这个数列满足ai≠aj(i≠j),现在要求你把这个数列从小到大排序,每次允许你交换其中任意一对数,请问最少需要几次交换?
输入格式:
第一行,正整数n (n<=100,000)。
以下若干行,一共n个数,用空格分隔开,表示数列{an},任意-2^31<ai<2^31。
输出格式:
只有一行,包含一个数,表示最少的交换次数。
样例输入:
8 8 23 4 16 77 -5 53 100
样例输出:
5
时间限制: 1000ms
空间限制: 128MB
这道题是一道贪心+排序的一道题目,想起来和实现起来其实并不难(可能我太菜了,所以搞了很久)。
代码实现:
#include<bits/stdc++.h>
using namespace std;
int n,a[1000001],cnt,b[1000001];
unordered_map<int,int>m;//储存a[i]的位置,其实就是一个哈希表,用unordered_map比map快
int main(){
cin>>n;
for(int i=1;i<=n;i++)cin>>a[i],b[i]=a[i],m.insert({a[i],i});//将a[i]存入对照数组b中,并将a[i]当前的位置存入哈希表
sort(b+1,b+1+n);//将对照数组b进行排序
for(int i=1;i<=n;i++){
if(b[i]!=a[i]){//如果元素a[i]不应该存在在这个位置上
cnt++;//步骤次数+1
swap(a[i],a[m[b[i]]]);//将a[i]交换到它应该到的位置上
m[a[m[b[i]]]]=m[b[i]];//更新a[i]在a数组中的位置
m[b[i]]=i;//同上
}
}
cout<<cnt;
return 0;
}