当前位置:首页 > 题解目录 > 正文内容

【题解】求逆序对个数

亿万年的星光4年前 (2022-04-09)题解目录1960

【题目描述】

有一实数序列A[1]、A[2] 、A[3] 、……A[n-1] 、A[n] (n<10000),若i<j,并且A[i]>A[j],则称A[i]与A[j]构成了一个逆序对,求数列A中逆序对的个数。

例如,5 2 4 6 2 3 2 6,可以组成的逆序对有

(5 2),(5 4),(5 2),(5 3),(5 2),

(4 2),(4 3),(4 2),

(6 2),(6 3),(6 2),

(3 2)

共:12个

【输入描述】

共两行,第一行有一个正整数n,第二行有n个整数。

【输出描述】

只有一行为逆序对个数。

【样例输入】

8
5 2 4 6 2 3 2 6

【样例输出】

12

所谓逆序对的问题,即对给定的数组序列,求其逆序对的数量。

从逆序对定义上分析,逆序对就是数列中任意两个数满足大的在前,小的在后的组合。如果将这些逆序对都调整成顺序(小的在前,大的在后),那么整个数列就变得有序,即排序。因而,容易想到冒泡排序的机制正好是利用消除逆序来实现排序的,也就是说,交换相邻两个逆序数,最终实现整个序列有序,那么交换的次数即为逆序对的数量。


当然,这个题目,用的是合并操作来分析。

在合并操作中,我们假设左右两个区间元素为:

左边:{3 4 7 9}     右边 {1 5 8 10}

那么,合并的第一步就是比较3和1,然后将1取出来,放到辅助数组中,这个时候我们发现,右边的区间如果是当前比较的较小值,那么其会于左边剩余的数字产生逆序关系,也就是说1和3、4、7、9都产生了逆序关系,我们可以一下子统计出4对逆序对。

接下来3,4取下来放到辅助数组后,5与左边剩下的7、9产生了逆序关系,我们可以统计出2对。

以此类推,8与9产生1对,那么总共有4+2+1对。这样统计的效率就会大大提高,便可较好地解决逆序对问题。                                                  

 

void msort(int s, int t){
	if(s==t) return ;  //如果只有一个数字则返回,无须排序
	int mid=(s+t)/2; 
	msort(s,mid);    //分解左序列
	msort(mid+1,t);  //分解右序列 
	int i=s, j=mid+1, k=s;  //接下来合并
	
	while(i<=mid && j<=t){
	
		if(a[i]<=a[j]){
			r[k]=a[i];
			k++;
			i++;
		}else{
			r[k]=a[j];
			k++;
			j++;
			ans+=mid-i+1; //统计产生逆序对的数量 
		}
	}
	while(i<=mid){  //复制 左边子序列剩余 
		r[k]=a[i];
		k++;
		i++;
	}
	while(i<=mid){  //复制 右边子序列剩余 
		r[k]=a[j];
		k++;
		j++;
	}
	for(int i=s;i<=t;i++)
		a[i]=r[i]; 
}


其中,ans+=mid-i+1; 这句代码统计新增逆序对的数量,ans作为全局变量,用于统计逆序对的数量,此时ans要增加左边区间剩余元素的个数。当归并排序结束后,逆序对问题也得到解决,ans即为逆序对的数量。

扫描二维码推送至手机访问。

版权声明:本文由青少年编程知识记录发布,如需转载请注明出处。

标签: 分治法
分享给朋友:

相关文章

【题解】后缀表达式的值

【题解】后缀表达式的值

【题目描述】从键盘读入一个后缀表达式(字符串),只含有0-9组成的运算数及加(+)、减(—)、乘(*)、除(/)四种运算符。每个运算数之间用一个空格隔开,不需要判断给你的表达式是否合法。以@作为结束标...

【题解】均分蛋糕

【题目描述】小明今天生日,他有n块蛋糕要分给朋友们吃,这n块蛋糕(编号为1到n)的重量分别为a1, a2, …, an。小明想分给每个朋友至少重量为k的蛋糕。小明的朋友们已经排好队准备领蛋糕,对于每个...

【题解】最小新整数

【问题描述】第⼀⾏有x个正整数a1,a2,..,ax,第⼆⾏有y个正整数b1,b2,...,by,第三⾏有z个正整数c1,c2,...,cz,假设第⼀⾏的x个正整数中的最⼤值为a、第⼆⾏的y个正整数中...

【题解】最大公约数(2019青岛市程序设计竞赛)

【问题描述】给定n,以及正整数序列a1,a2,…,an与b1,b2,…,bn。令:sa=a1*a2*…*ansb=b1*b2*…*bn求sa和sb的最大公约数gcd(sa,sb)。【输入】第一行n。第...

【题解】发工资

【题目描述】财务处的小李最近就在考虑一个问题:如果每个员工的工资额都知道,最少需要准备多少张人民币,才能在给每位员工发工资的时候都不用员工找零呢?这里假设程序猿的工资都是正整数,单位元,人民币一共有1...

【题解】马拦过河卒

【题解】马拦过河卒

【题目描述】棋盘上A点有一个过河卒,需要走到目标B点。卒行走的规则:可以向下、或者向右。同时在棋盘上C点有一个对方的马,该马所在的点和所有跳跃一步可达的点称为对方马的控制点。因此称之为“马拦过河卒”。...