逆序数的求法

逆序数:

也是就说,对于n个不同的元素,先规定各元素之间有一个标准次序(例如n个 不同的自然数,可规定从小到大为标准次序),于是在这n个元素的任一排列中,当某两个元素的先后次序与标准次序不同时,就说有1个逆序。一个排列中所有逆序总数叫做这个排列的逆序数。
在一个排列中,如果一对数的前后位置与大小顺序相反,即前面的数大于后面的数,那么它们就称为一个逆序。一个排列中逆序的总数就称为这个排列的逆序数。逆序数为偶数的排列称为偶排列;逆序数为奇数的排列称为奇排列。如2431中,21,43,41,31是逆序,逆序数是4,为偶排列。

如数列 3 5 4 8 2 6 9

(5,4)是一个逆序对,同样还有(3,2),(5,2),(4,2)等等。

什么是逆序数:
     跟标准列相反序数的总和 
     比如说: 
标准列是1 2 3 4 5 
那么 5 4 3 2 1 的逆序数算法:

  1. 5之前没有数,记为0.
    看第二个,4之前有一个5,在标准列中5在4的后面,所以记1个 
    类似的,第三个 3 之前有 4 5 都是在标准列中3的后面,所以记2个 
    同样的,2 之前有3个,1之前有4个 
    将这些数加起来就是逆序数=1+2+3+4=10 
    再举一个 2 4 3 1 5 
    4 之前有0个 
    3 之前有1个 
    1 之前有3个 
    5 之前有0个 
    所以逆序数就是1+3=4

逆序数的求法:

1.一个一个的数

最简单也是最容易想到的方法就是,对于数列中的每一个数a[i],遍历数列中的数a[j](其中j<i),若a[i]<a[j],则逆序数加1,这样就能统计出该数列的逆序数总和

该方法的时间复杂度为O(n^2)

2.归并思想

有一种排序的方法是归并排序,归并排序的主要思想是将整个序列分成两部分,分别递归将这两部分排好序之后,再和并为一个有序的序列.

在合并的过程中是将两个相邻并且有序的序列合并成一个有序序列,如以下两个有序序列

Seq1:3  4  5

Seq2:2  6  8  9

合并成一个有序序:

Seq:2  3  4  5  6  8  9

对于序列seq1中的某个数a[i],序列seq2中的某个数a[j],如果a[i]<a[j],没有逆序数,如果a[i]>a[j],那么逆序数为seq1中a[i]后边元素的个数(包括a[i]),即len1-i+1,

这样累加每次递归过程的逆序数,在完成整个递归过程之后,最后的累加和就是逆序的总数

再如:

0 1 2 3 4

2 3 4 1 5

mid=2;

seq1:2 3 4

seq2:1 5

2>1 count=mid-i+1=2-0+1=3;所以,逆序数为3.

代码:

#include<iostream>
#include<climits>
using namespace std;
 
int count=0;
 
void merge(int arr[],int first,int mid,int last)
{
     
    int *tmpArr=new int[last-first+1];
    int i=first,j=mid+1;
    int cur=0;
    while(i<=mid && j<=last)
    {
        if(arr[i]<arr[j])
        {
            tmpArr[cur++]=arr[i++];
        }
        else
        {
            tmpArr[cur++]=arr[j++];
 
            count += mid-i+1;//只增加这一句便可求逆序数
        }
    }
    if(i<=mid)
    {
        while(i<=mid)
            tmpArr[cur++]=arr[i++];
    }
    else
    {
        while(j<=last)
            tmpArr[cur++]=arr[j++];
    }
 
 
    for(int k=0;k<cur;k++)
    {
        arr[first++]=tmpArr[k];
    }
    delete[] tmpArr;
    tmpArr=NULL;
}
 
 
 
void mergeSort(int arr[],int first,int last)
{
    if(first==last)
        return;
    int mid=(first+last)/2;
    mergeSort(arr,first,mid);
    mergeSort(arr,mid+1,last);
    merge(arr,first,mid,last);
}
int main()
{
    //int a1[]={7,8,9,1,2,3,5};
    //int a1[]={5,4,3,2,1}; //count=10
    int a1[]={2,3,4,1,5}; //count=3
     
    int len=sizeof(a1)/sizeof(a1[0]);
    mergeSort(a1,0,len-1);
    cout<<count<<endl;
}

结果:

3

posted @ 2014-02-28 16:51  mickole  阅读(1551)  评论(0)    收藏  举报