邓俊辉算法训练营习题 最小交换

最小交换
时间限制:1 sec

空间限制:256 MB

问题描述
给定一个 1 到 n 的排列(即一个序列,其中 [1,n] 之间的正整数每个都出现了恰好 1 次)。

你可以花 1 元钱交换两个相邻的数。

现在,你希望把它们升序排序。求你完成这个目标最少需要花费多少元钱。

输入格式
第一行一个整数 n,表示排列长度。

接下来一行 n 个用空格隔开的正整数,描述这个排列。

输出格式
输出一行一个非负整数,表示完成目标最少需要花多少元钱。

样例输入
3
3 2 1
样例输出
3
样例解释
你可以:

花 1 元交换 1,2,序列变成 3 1 2。

花 1 元交换 1,3,序列变成 1 3 2。

花 1 元交换 2,3,序列变成 1 2 3。

总共需要花 3 元。

可以证明不存在更优的解。

数据范围
对于 20% 的数据,保证 n<=7。

对于 60% 的数据,保证 n<=1,000。

对于 100% 的数据,保证 n<=200,000。

#include <iostream>
#include <cstdio>
#include <vector>

using namespace std;

int ans = 0;//计数
vector<int> line;//各个元素
vector<int> NewLine;//存储新排列好的序列
int merger(int l,int r){
    if(l >= r) //l == r --> 一个元素 无法归并
        return 0;

    int mid = r >> 1;//向左移1位 即利用二进制的性质 二分
    merger(l,mid);//归并前驱序列
    merger(mid + 1,r);//归并后驱序列

    int q = l,p = mid + 1;
    //p > r代表右半部分已经归并完成
    //q <= mid && line[q] < line[p] -> 前驱序列的元素更小
    if(p > r || q <= mid && line[q] < line[p])
        NewLine.push_back(line[q++]);//q++ ->将q移到下一位
    else{
        NewLine.push_back(line[p++]);
        ans += mid - q + 1;//参考冒泡排序(已证明最少的交换次数即冒泡交换次数)
    }
    return ans;//返回交换次数
}
int getAnswer(int n){
    int l = 0,r = n - 1;
    return merger(l,r);
}
int main(int argc, char const *argv[]) {
    //n 代表元素数目
    int n;
    scanf("%d",&n);

    for(int i = 0;i < n;i++){
        int a;
        scanf("%d",&a);
        line.push_back(a);
    }
    printf("%d",getAnswer(n));
    return 0;
}


 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值