求排列的逆序数
来源:互联网 发布: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
- 求排列的逆序数
- 求排列的逆序数
- 求排列的逆序数
- 求排列的逆序数
- 求排列的逆序数
- 求排列的逆序数<归并><C++>
- 百练 求排列的逆序数
- 7622:求排列的逆序数
- 分治之求排列的逆序数
- java实现求排列的逆序数
- poj求排列的逆序数
- 0811 OpenJ#求排列的逆序数
- 排列的逆序数
- 066day(求排列的逆序数的尝试)
- Kendall tau距离:求两个排列之间的逆序数
- |NOIOJ|二分归并|7622:求排列的逆序数
- Kendall tau距离:求两个排列之间的逆序数
- 分治之归并排序 求排列的逆序数
- 136. Single Number异或
- NVIDIA GameWorks and UE4
- NGUI3.11 离线Document文档
- css图片等比列放大
- HM编码器代码阅读(35)——帧内预测(二)帧内预测总流程
- 求排列的逆序数
- windows和linux进程间与线程间通信
- leetcode 113. Path Sum II
- 数据单向绑定
- Ubuntu16.4 安装 redis
- 集中日志服务器Rsyslog
- poj3304Segments(线段与直线相交)
- 《JS高程(3)》DOM2和DOM3-样式、视口尺寸问题-第12章笔记(23)
- js创建新的节点