逆序对这个东西就是说 2,1这里2>1所以呢 2,1就是一个逆序对,然后2,1,5,4,3这个序列里面呢(2,1),(5,4),(4,3)一共有三个逆序对。在给出的一个序列里面查找出一共有多少个逆序对。
正常的想法都是利用两重循环,来进行检测,这样的话,时间复杂度是n2,有没有比这个更好的呢? 就是利用分治算法,但是虽然分治,但是也要进行一些别的,不是单单的进行分组,比如说对于数组d来说,可以分成两组a,b,然后把a,b的逆序对分别找出来,然后再把a和b的逆序对一块找出来,再把三个加和就可一了
这里分别进行寻找都好说,就是把两个a,b合并,再找就不好解决,因为我没有找到高效点的方法,所以看了一下别人的代码,发现可以在查找完a,b后呢,可以将a,b分别进行排序,然后就可以了,并且会降低时间复杂度,具体的代码下面,并吧关键的部分贴上注释了:
/*************************************************************************
> File Name: /home/qc/linux/test.cpp
> Author: qiuchang
> Mail: beijing.qiuchang@163.com
> Created Time: 2014年03月06日 星期四 08时08分39秒
************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int mix_number(int* tmp, int *a, int x, int y, int m, int n)
{
int count = 0;
int i = x;
int j = m;
int k = 0;
//这里的while循环并没有让j每次都从0开始
//如果从0开始那么他的效率又会长上去,所以利用
//数列已经排好的优势,把效率降下来
for(i=x; i<=y; ++i)
{
while( j<=n && a[i] > a[j] )
++j;
count += j-m;
}
i = x;
j = m;
while(i<=y && j<=n)
{
if( a[i] <= a[j] )
tmp[k++] = a[i++];
else
tmp[k++] = a[j++];
}
while( i <= y )
{
tmp[k++] = a[i++];
}
while( j <= n )
{
tmp[k++] = a[j++];
}
return count;
}
int div_number(int *a, int i, int j)
{
if( i < j )
{
int mid = i + ((j-i)>>1);
int v1 = div_number(a, i, mid);
int v2 = div_number(a, mid+1, j);
int tmp[10] = {0};
int v3 = mix_number(tmp, a, i, mid, mid+1, j);
//这里就是把原来的数组进行排序
memcpy(a+i, tmp, sizeof(int)*(j-i+1));
return v1+v2+v3;
}
else
return 0;
}
int main()
{
int a[] = {9,5,2,3,1};
printf("%d\n", div_number(a, 0, 4));
return 0;
}