归并排序求排列的逆序数

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

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

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

猜你喜欢

转载自blog.csdn.net/qq_40507857/article/details/81176865
今日推荐