逆序对

本文详细介绍了求解数组中逆序对个数的问题,对比了两种方法:最原始的两重循环枚举与更高效的归并排序思想。通过分析,展示了归并排序不仅在时间复杂度上优于原始方法,同时提供了求解逆序对个数的实用算法。此外,文章还探讨了顺序对个数的统计,深入理解数组排序与逆序关系。
摘要由CSDN通过智能技术生成

逆序对


设 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);
	}
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值