描述
-
在Internet上的搜索引擎经常需要对信息进行比较,比如可以通过某个人对一些事物的排名来估计他(或她)对各种不同信息的兴趣,从而实现个性化的服务。
对于不同的排名结果可以用逆序来评价它们之间的差异。考虑1,2,…,n的排列i1,i2,…,in,如果其中存在j,k,满足 j < k 且ij > ik,那么就称(ij,ik)是这个排列的一个逆序。
一个排列含有逆序的个数称为这个排列的逆序数。例如排列 263451 含有8个逆序(2,1),(6,3),(6,4),(6,5),(6,1),(3,1),(4,1),(5,1),因此该排列的逆序数就是8。显然,由1,2,…,n 构成的所有n!个排列中,最小的逆序数是0,对应的排列就是1,2,…,n;最大的逆序数是n(n-1)/2,对应的排列就是n,(n-1),…,2,1。逆序数越大的排列与原始排列的差异度就越大。
现给定1,2,…,n的一个排列,求它的逆序数。
输入
-
第一行是一个整数n,表示该排列有n个数(n <= 100000)。
第二行是n个不同的正整数,之间以空格隔开,表示该排列。
输出
- 输出该排列的逆序数。
样例输入
-
6 2 6 3 4 5 1
样例输出
-
8
提示
-
1. 利用二分归并排序算法(分治);
2. 注意结果可能超过int的范围,需要用long long存储。
思路:就像题目的提示一样,利用归并排序,一边排序,一边统计此时的逆序数,最后将结果累加就可以,注意数字的范围!
import java.util.*;
public class Merge_Sort {
static int[] a;
static int[] tmp;
static long sum = 0;
static long merge(int a[],int tmp[],int start,int end,int center){
//将数组a的局部a[s,center]和a[center + 1,e]合并到tmp,并保证tmp有序,然后再拷贝回a[s,m]
//归并操作时间复杂度:O(e-m+1),即O(n)
int pb = 0;
int p1 = start , p2 = center + 1;
long k = 0;
while (p1 != center + 1){ //在这里开始这个部分的统计,具体为什么是center+1,自己试试吧
while (p2 != end + 1 && a[p1] < a[p2]){
p2++;
}
k += end - p2 + 1 ; //统计属于a[p1]的逆序数,之后累加
p1++;
}
p1 = start; //统计完之后进行数值的归位,进行下一次的归并
p2 = center + 1 ;
while( p1 <= center && p2 <= end){
if( a[p1] > a[p2])
tmp[pb++] = a[p1++];
else
tmp[pb++] = a[p2++];
}
while( p1 <= center)
tmp[pb++] = a[p1++];
while( p2 <= end)
tmp[pb++] = a[p2++];
for(int i=0;i<=end-start;i++){
a[start + i] = tmp[i];
}
return k;
}
static void merge_Sort(int a[],int tmp[],int start,int end){
if( start < end){
int center = start + (end - start) / 2;
merge_Sort(a, tmp, start, center);
merge_Sort(a, tmp, center + 1, end);
sum += merge(a, tmp, start, end, center); //将所有的逆序数统计结果相加
}
}
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int n;
System.out.print("Please input arrays length:");
n = input.nextInt();
a = new int[n];
tmp = new int[n];
for(int i = 0 ; i < a.length;i++){
a[i] = input.nextInt();
}
merge_Sort(a, tmp, 0, n-1);
/*for(int i = 0 ; i < a.length;i++)
System.out.print(a[i] + " ");
System.out.println();*/
System.out.println(sum);
}
}
/*
6
2 6 3 4 5 1
*/
运行结果: