求排列的逆序数

来源:互联网 发布:linux书籍 编辑:程序博客网 时间:2024/05/07 08:17

描述

在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个不同的正整数,之间以空格隔开,表示该排列。

输出


输出该排列的逆序数。

样例输入


62 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++];elsetmp[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);}}/*62 6 3 4 5 1*/

运行结果:


0 0
原创粉丝点击