• 归并排序与逆序对


    算法导论上2-4是这样一个题目:

    设A[1...n]是一个包含n个不同数的数组。如果在i<j的情况下,有A[i]>A[j],则(i, j)就称为A中的一个逆序对(inversion)。试给出一个算法,它能用O(nlgn)的最坏情况运行时间确定n个元素的任何排列中逆序对的数目。

    咋一看没有什么思路,可一看见提示赫然给出:修改归并排序,于是顿悟。其实,只需要在归并排序中加上一个计数器,在每次merge的时候计算逆序对,这样就可以算出总共的逆序对了。

    #include <iostream>
    using namespace std;
    void merge_sort(int *A,int p, int r);
    void merge(int *A,int p, int q, int r);
    const int max_int = 0x7fffffff;
    int sum = 0;
    int main()
    {
    // int a[]={
    // 82,91,14,91,64,11,29,55,96,97,17,97,96,49,80
    //
    //,15,43,92,79,96,66, 5,85,93,68,76,75,40,66,18
    //
    //,71, 4,28, 6,11,83,70,32,95, 4,44,39,77,80,20
    //
    //,49,45,65,71,76,28,68,66,17,13,50,96,35,59,23
    //
    //,75,26,51,70,89,96,55,15,16,26,84,26,82,25,93
    //
    //,36,20,26,62,48,36,83,59,55,92,29,76,76,39,57
    //
    //, 9, 6,54,78,93,14,57,47, 2,34} ;
    int a[]={7,3,2,5,1,4,5,9,100,1};
    int i;
    int length = sizeof(a)/sizeof(int);
    for(i=0;i<length;++i)
    cout<<a[i]<<(i%10==9?'\n':' ');
    merge_sort(a,0,length-1);
    cout<<"\nafter merge_sort: \n";
    for(i=0;i<length;++i)
    cout<<a[i]<<(i%10==9?'\n':' ');
    cout<<"total number of iversion is: "<<sum<<endl;
    }
    void merge_sort(int *A,int p, int r)
    {
    int q;
    if(p < r)
    {
    q = (p + r)/2;
    merge_sort(A,p,q);
    merge_sort(A,q+1,r);
    merge(A,p,q,r);
    }
    }
    void merge(int *A,int p, int q, int r)
    {
    int n1 = q-p+1;
    int n2 = r-q;
    int *L = new int[n1+1];
    int *R = new int[n2+1];
    int i,j,k;
    for(i=0;i<n1;++i)
    L[i] = A[p+i];
    for(j=0;j<n2;++j)
    R[j] = A[q+j+1];
    L[n1] = max_int;
    R[n2] = max_int;
    i=0;j=0;
    for(k=p;k<=r;++k)
    {
    if(L[i]<=R[j])
    A[k]=L[i++];
    else
    {
    A[k]=R[j++];
    sum+=n1-i;
    }
    }
    }

    再上网搜,发现这种方法已经被无数人研习过,poj2299就是一道典型的求逆序对的题。于是蒻人欣欣然修改代码submit等待AC,结果出现memory limited exceeded。观察数据规模和自己的代码,需要进行若干处修改:

    • sum得用64位整型:long long;
    • 各个数组在全局申请,不要动态申请,也不要在main函数中申请;
  • 相关阅读:
    Linux中的防火墙
    Jinja2模板概述
    Ansible触发器-tag标签-忽略错误
    Ansible流程控制
    Ansible变量
    Play-book格式写法
    Redis哨兵(Sentinel)
    Redis 主从复制
    Redis介绍及安装
    Keepalived高可用集群搭建
  • 原文地址:https://www.cnblogs.com/bovine/p/2185006.html
Copyright © 2020-2023  润新知