数列排序——模拟

发布时间:2024年01月24日

给定一个数列 a,这个数列满足ai != aj(i != j),现在要求你把这个数列从小到大排序,每次允许你交换其中任意一对数,请问最少需要几次交换?

输入
第一行是一个整数,代表数字个数n(1 ≤ n ≤ 1e5).
第二行有n个整数用空格分隔开,表示数列a(?2e31< ai <2e31?1).

输出
只有一行,包含一个数,表示最少的交换次数。

Input
8
8 23 4 16 77 -5 53 100
Output
5
解析:
快排后的位置应该是每个数的最终位置,也就是说如果一个数移动到相应的位置后,就不用动了,这样的交换应该就是交换次数最少的。
如样例产生的效果:
8 23 4 16 77 -5 53 100
-5 23 4 16 77 8 53 100
-5 4 23 16 77 8 53 100
-5 4 8 16 77 23 53 100
-5 4 8 16 77 23 53 100
-5 4 8 16 23 77 53 100
-5 4 8 16 23 53 77 100
-5 4 8 16 23 53 77 100
-5 4 8 16 23 53 77 100

#include <bits/stdc++.h>
using namespace std;
#define int long long
#define endl '\n'
#define ios ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
int gcd(int a,int b) { return b? gcd(b,a%b) : a; }
typedef pair<int,int> PII;
const double PI=acos(-1.0);
const int N=2e6+10;
struct node
{
    int x,id;
}str[N];
bool cmp(node a,node b)
{
    return a.x<b.x;
}
int a[N];
int n;
void solve()
{
    cin>>n;
    for (int i=1;i<=n;i++)
    {
        cin>>a[i];
        str[i]={a[i],i};
    }
    sort (str+1,str+n+1,cmp);
    int ans=0;
    for (int i=1;i<=n;i++)
    {
        if (a[i]!=str[i].x)
        {
            ans++;
            int t=a[i];
            swap(a[i],a[str[i].id]);        //交换两个数的位置
            int l=i+1,r=n;
            while (l<r)
            {
                int mid=l+r>>1;
                if (str[mid].x>=t) r=mid;
                else l=mid+1;
            }
            str[l].id=str[i].id;            //相应的更新数a[i]的位置,由原来的str[l].id变成了str[i].id
        }
    }
    cout<<ans;
}
signed main()
{
    ios;
    int T=1;
    //cin>>T;
    while (T--) solve(); 
    return 0;
}

文章来源:https://blog.csdn.net/m0_74403543/article/details/135829947
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。