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

逆序对这个东西就是说 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;
}
    原文作者:查找算法
    原文地址: https://blog.csdn.net/qiuchang008/article/details/22601329
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞