博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
hihoCoder_二分·归并排序之逆序对
阅读量:6855 次
发布时间:2019-06-26

本文共 2500 字,大约阅读时间需要 8 分钟。

一.题目

题目1 : 二分·归并排序之逆序对

时间限制:10000ms
单点时限:1000ms
内存限制:256MB

描写叙述

在上一回、上上回以及上上上回里我们知道Nettle在玩《艦これ》。经过了一番苦战之后。Nettle又获得了的非常多非常多的船。

这一天Nettle在检查自己的舰队列表:
我们能够看到。船默认排序是以等级为參数。但实际上一个船的火力值和等级的关系并不大,所以会存在A船比B船等级高,可是A船火力却低于B船这种情况。比方上图中77级的飞龙改二火力就小于55级的夕立改二。
如今Nettle将依照等级高低的顺序给出全部船的火力值,请你计算出一共同拥有多少对船满足上面提到的这样的情况。

输入

第1行:1个整数N。N表示舰船数量, 1≤N≤100,000

第2行:N个整数。第i个数表示等级第i低的船的火力值a[i],1≤a[i]≤2^31-1。

输出

第1行:一个整数。表示有多少对船满足“A船比B船等级高,可是A船火力低于B船”。

例子输入
101559614248 709366232 500801802 128741032 1669935692 1993231896 369000208 381379206 962247088 237855491
例子输出
27

二.解题技巧

    依据题目的提示,这道题能够使用二分归并排序来对数组进行排序的同一时候,统计逆序数的个数。

详细做法是将两个子问题进行二分归并排序后得到的逆序数加上将子问题进行归并的时候。后面一半的元素移动的位置来得到终于的逆序数。

三.实现代码

#include <iostream>
#include <vector>
using namespace std;
long long Merge(vector<int>::iterator BeginIte, int Number)
{
    if (Number < 2)
    {
        return 0;
    }
    int Mid = Number / 2;
    int IndexFirst = 0;
    int IndexSecond = Mid;
    vector<int> TmpArray;
    long long Count = 0;
    int Index = 0;
    while ((IndexFirst < Mid) && (IndexSecond < Number))
    {
        int TmpFirst = *(BeginIte + IndexFirst);
        int TmpSecond = *(BeginIte + IndexSecond);
        if (TmpFirst > TmpSecond)
        {
            TmpArray.push_back(TmpSecond);
            Count += IndexSecond++ - Index++;
        }
        else
        {
            TmpArray.push_back(TmpFirst);
            IndexFirst++;
            Index++;
        }
    }
    while (IndexFirst < Mid)
    {
        TmpArray.push_back(*(BeginIte + IndexFirst++));
    }
    while (IndexSecond < Number)
    {
        TmpArray.push_back(*(BeginIte + IndexSecond++));
    }
     // copy the array back
    for (int Index = 0; Index < Number; Index++)
    {
        *(BeginIte++) = TmpArray[Index];
    }
    return Count;
}
long long MergeSort(vector<int>::iterator BeginIte, int Number)
{
    if (Number < 2)
    {
        return 0;
    }
    int Mid = Number / 2;
    long long Count = 0;
    Count += MergeSort(BeginIte, Mid);
    Count += MergeSort(BeginIte + Mid, Number - Mid);
    Count += Merge(BeginIte, Number);
    return Count;
}
int main()
{
    int Number = 0;
    cin >> Number;
    int Index = 0;
    vector<int> Array;
    while (Index++ < Number)
    {
        int Tmp = 0;
        cin >> Tmp;
        Array.push_back(Tmp);
    }
    cout << MergeSort(Array.begin(), Number) << endl;
//    for (int Index = 0; Index < Number; Index++)
//    {
//        cout << Array[Index] << endl;
//    }
    // cout << "The result is " << Count << endl;
    return 0;
}

四.体会

    这道题让我长了见识,我记得我曾经的做法是先使用STL里面的sort函数对数组进行排序,然后依据排序后的数组的元素的下标与同样元素在原来数组里面的下标的关系。来计算逆序对的个数(也就是逆序数)。

这样的方法不仅须要进行排序的时间O(nlgn),在使用hash_table的时候,还须要O(n)的时间来推断元素在排序后的数组的下标与原来数组的下标的关系,略微有些复杂。

    这道题使用二分归并排序在进行排序的同一时候,也递归计算量数组中的逆序对的个数。是一种非常有用的方法。

这样的方法主要是基于数组中的逆序对的个数等于子问题中存在的逆序对的个数加上归并过程中存在的逆序对的个数。归并过程中存在的逆序对的个数等于后面一半的元素移动到正确位置时须要移动的位数的和。

版权全部。欢迎转载,转载请注明出处,谢谢微笑
你可能感兴趣的文章
Python 学习(四)
查看>>
SUSE 开发者提议在 GCC 编译器中用 Python 替代 AWK
查看>>
0034-CM启动报InnoDB engine not found分析
查看>>
从奇葩说学到的解题方法
查看>>
源码分析Retrofit请求流程
查看>>
枚举类
查看>>
MySQL 5.6关闭DNS查询
查看>>
第二十章:异步和文件I/O.(四)
查看>>
WPF字体图标——FontAwesom
查看>>
深入剖析Redis - Redis集群模式搭建与原理详解
查看>>
这些Spring中的设计模式,你都知道吗?
查看>>
标准坐标系与火星坐标系(高德)百度坐标系之间互转
查看>>
运维小哥的工作自述
查看>>
嵌入式设备的发展:解决复杂的设计挑战
查看>>
【UGUI】 (一)------- 放大镜
查看>>
spring boot2 整合(四)定时任务Scheduled || Quartz并持久化
查看>>
阿里巴巴“新18罗汉”养成记
查看>>
centos7 yum安装zabbix图解
查看>>
jQuery 解决 click 和 dblclick 冲突
查看>>
基于Numpy的线性代数运算
查看>>