逆序对

逆序对


设 A 为一个有 n 个数字的有序集 (n>1),其中所有数字各不相同。

如果存在正整数 i, j 使得 1 ≤ i < j ≤ n 而且 A[i] > A[j],则 <A[i], A[j]> 这个有序对称为 A 的一个逆序对,也称作逆序数。

定义

对于一个包含N个非负整数的数组A[1..n],如果有i < j,且A[ i ]>A[ j ],则称(A[ i] ,A[ j] )为数组A中的一个逆序对。
例如,数组(3,1,4,5,2)的逆序对有(3,1),(3,2),(4,2),(5,2),共4个。

求解逆序对个数问题

问题描述

给定一 数组 ,求该 数组中包含多少个逆序对。

求解方法

方法一:最原始的方法,利用两重循环进行枚举。该算法的时间复杂度为O(n^2)。
C++代码如下:

int count_inversion(int *a, int N)
{
    int count = 0;
    int i, j;
    for(i=0; i<N-1; i++)
        for(j=i+1; j<N; j++)
            if(a[i]>a[j])
            count++;
    return count;
}


方法二:
归并排序的思想求解逆序对的个数,这是解决该问题的一种较为高效的算法。该算法的时间复杂度为O(nlogn)。

int inversion_count = 0; // 记录逆序对个数
int count = 0; // 记录顺序对个数

void merge(int *src, int *des, int start, int mid, int end)
{
	int i = start, j = mid + 1;
	int k = start;

	while (i != mid + 1 && j != end + 1)
	{
		if (src[i] < src[j])
		{
			des[k++] = src[i++];
			count += end - j + 1;  // 统计“顺序对”个数
		}
		else 
		{
			des[k++] = src[j++];			
			inversion_count += mid - i + 1;  // 统计“逆序对”个数
		}
	}
	while (i != mid + 1) des[k++] = src[i++];
	while (j != end + 1) des[k++] = src[j++];
	for (i = start; i != end + 1; ++i)
		src[i] = des[i];
}

void mergeSort(int *src, int *des, int start, int end)
{
	int mid;
	if (start < end)
	{
		mid = (start + end) >> 1;
		mergeSort(src, des, start, mid);
		mergeSort(src, des, mid + 1, end);
		merge(src, des, start, mid, end);
	}
}



你可能感兴趣的:(算法,归并排序,逆序对,顺序对)