利用分治算法,来完成逆序对的查找

来源:互联网 发布:it服装官网 编辑:程序博客网 时间:2024/06/06 06:39

逆序对这个东西就是说 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++];elsetmp[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;}elsereturn 0;}int main(){int a[] = {9,5,2,3,1};printf("%d\n", div_number(a, 0, 4));return 0;}


0 0