zoukankan      html  css  js  c++  java
  • 递归O(NlgN)求解逆序数

    导言

    第一次了解到逆序数是在高等代数课程上。当时想计算一个数列的逆序数直觉就是用两重循环O(n^2)暴力求解。现在渐渐对归并算法有了一定的认识,因此决定自己用C++代码小试牛刀。

    逆序数简介

    由自然数12…,n组成的不重复的每一种有确定次序的排列,称为一个n级排列(简称为排列);或者一般的,n个互不同元素排成一列称为“一个n级排列”。例如,12344312都是4级排列,而24315是一个5级排列。

    在一个n级排列中,如果一对数的前后位置与大小顺序相反,即前面的数大于后面的数,那么它们就称为一个“逆序”。

    例子:
      123成为自然排列 逆序数为 0
      324一列数 逆序排列有(32) (31) (21) (41) 所以逆序数是4

     

    代码实现

     

    #include <cstdio>
    #include <cstring>
    
     
    
    const int N = 4;   //测试数组的大小
    
    int cnt;  //全局变量
    
     
    
    void mergeSort(int *a,int p,int q,int *T){
    
        if(p+1>=q) return;
    
        int m=p+(q-p)/2;
    
        mergeSort(a,p,m,T);
    
        mergeSort(a,m,q,T);
    
        //merge
    
        for(int x=p,y=m,i=p;i<q;i++){
    
            if(x<m&&y<q&&a[x]<a[y] || y>=q) T[i]=a[x++];   //往‘左边’加
    
            else{
    
                
    
                T[i] = a[y++];
    
                cnt += (m-x);   //此处为重点,每向加入右边部分一个数时,逆序数应增加左边尚未被加入T的元素个数
    
            }
    
        }
    
        for(int i=p;i<q;i++)
    
            a[i] = T[i];
    
    }
    
    int main(){
    
        int T[N];   //辅助数组,即额外空间代价O(N)
    
        int a[]={3,2,4,1};
    
        cnt = 0;  //初始cnt为0
    
        mergeSort(a,0,N,T);
    
        printf("逆序数为:%d
    ",cnt);
    
        return 0;
    
    }

    结语

    对比先前两重循环暴力求解逆序数的做法,可以证明归并求解的时间复杂度是O(NlgN)。因此,当N较大时,可以发现本归并算法的明显高效很多。

  • 相关阅读:
    Linux文件属性
    [Oracle] Listener的动态注册
    jQuery easyUI Pagination控件自定义div分页(不用datagrid)
    桂林电子科技大学出校流量控制器Android版1.0.0
    php使用check box
    Python windows ping
    Python selenium chrome 环境配置
    Linux wget auto login and backup database
    PyQt4 ShowHMDB show sqlite3 with QTableWidget summary
    PyQt4 py2exe 打包 HardwareManager
  • 原文地址:https://www.cnblogs.com/SeaSky0606/p/4567805.html
Copyright © 2011-2022 走看看