归并排序求排列的逆序数

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_40507857/article/details/81176865

在一个排列中,如果一对数的前后位置与大小顺序相反,即前面的数大于后面的数,那么它们就称为一个逆序

一个排列中逆序的总数就称为这个排列的逆序数。逆序数为偶数的排列称为偶排列;逆序数为奇数的排列称为奇排列

1.排列有奇排列和偶排列,奇排列不能转化成偶排列,偶排列不能转化成奇排列

2.有一个随机排列,用f(x)(x!=0)表示数字x前面比它小的数的个数,
全部数字的f(x)之和为y,若y为奇数,则称为奇排列,否则是偶排列
例如:

排列871526340,y=0+0+0+1+1+3+2+3=10,偶排列
排列871625340,y=0+0+0+1+1+2+2+3=9,奇排列
3.逆序数也可以理解为将一个随机排列通过交换成为升序排列的最小交换次数

归并排序求排列的逆序数:时间复杂度 N*log(N)

函数接口:a[0...n-1] ,cnt=0; call: MergeSort(0, n);

逆序数为cnt;

#include<cstdio>
const int maxn =1e4+10;
int a[maxn];
int c[maxn];
int cnt;

void MergeSort(int l, int r)
{
    int mid, i, j, tmp;
    if (r > l + 1)
    {
        mid = (l + r) / 2;
        MergeSort(l, mid);
        MergeSort(mid, r);
        tmp = l;
        for (i = l, j = mid; i < mid && j < r;)
        {
            if (a[i] > a[j])
            {
                c[tmp++] = a[j++];
                cnt += mid - i;
            }
            else
            {
                c[tmp++] = a[i++];
            }
        }
        if (j < r)
        {
            for (; j < r; ++j)
            {
                c[tmp++] = a[j];
            }
        }
        else
        {
            for (; i < mid; ++i)
            {
                c[tmp++]=a[i];
            }
        }
        for (i = l; i < r; ++i)
        {
            a[i] = c[i];
        }
    }
    return ;
}

int main()
{
	int N;
	while(scanf("%d",&N)!=EOF)
	{
		for(int i=0;i<N;i++)
		scanf("%d",&a[i]);
		cnt=0;
		MergeSort(0,N);
		printf("%d\n",cnt);
	}
	return 0;
}

 

展开阅读全文

没有更多推荐了,返回首页