逆序数个数 (Inversion Counting) - Merge and Sort
来源:互联网 发布:oracle的端口 编辑:程序博客网 时间:2024/05/11 03:59
普林斯顿的算法课质量很赞,这次作业中涉及到一个"逆序数"的知识,正好在之前学习mergesort时有一道课后提供的面试题与之相关,于是试着实现了。
原题链接:http://www.practice.geeksforgeeks.org/problem-page.php?pid=558
Given an array, find inversion count of array.
Inversion Count for an array indicates – how far (or close) the array is from being sorted. If array is already sorted then inversion count is 0. If array is sorted in reverse order that inversion count is the maximum.
Formally speaking, two elements a[i] and a[j] form an inversion if a[i] > a[j] and i < j.
The sequence 2, 4, 1, 3, 5 has three inversions (2, 1), (4, 1), (4, 3).
Input:
The first line of input contains an integer T denoting the number of test cases.
The first line of each test case is N,N is the size of array.
The second line of each test case contains N input C[i].
Output:
Print the inversion count of array.
Constraints:
1 ≤ T ≤ 100
1 ≤ N ≤ 100
1 ≤ C ≤ 500
Example:
Input:
1
5
2 4 1 3 5
Output:
3
在一次merge中,数组的指标i是从前到后的index,j是从后到前的index,i和j不能越过数组一半的地方,这是由于数组是对半分好,前后两半排好序再merge,这是mergesort典型的模式。在设置好计数器为0后,在一次sort递归中我们需要做的只有两件事,第一,把计数器cnt加上sort前半部分、sort后半部分得到的逆序数加起来,第二,把cnt加上merge过程中找到的逆序数个数。
在一次merge中,每次从存储原来数组的辅助数组aux向要排好序的数组a添加元素时不外乎4个情况,
aux[i]不比aux[j]大,也就是目前前半部分最小值不比后半部分最小值大,把aux[i]添加到a[],不产生新的逆序对
aux[i]更大,这时从中间位置开始往左一直到aux[i],所有的数都比目前后半部分的最小值aux[j]更大,产生相应个数的逆序对
i已用尽(增加至超过一半)那么肯定是aux[j],
j已用尽(减少过半)那么肯定是aux[i],这两个情况下添加元素都不会导致新的逆序数,因为已经在第二种情况中被考虑过了
其余代码均于原本的mergesort如出一辙
import java.util.Scanner;class InversionCount { private static int mergeAndCount(int[] a, int[] aux, int lo, int mid, int hi) { for (int k = lo; k <= hi; k++) aux[k] = a[k]; // assume that a[lo:mid] and a[mid+1:hi] are sorted int cnt = 0; // counter of inversions int i = lo, j = mid + 1; for (int k = lo; k <= hi; k++) { if (i > mid) { // i is exhausted a[k] = aux[j++]; } else if (j > hi) { // j is exhausted a[k] = aux[i++]; } else if (aux[j] < aux[i]) { cnt += mid + 1 - i; a[k] = aux[j++]; } else { a[k] = aux[i++]; } } return cnt; } private static int sortAndCount(int[] a, int[] aux, int lo, int hi) { if (hi <= lo) return 0; int mid = (lo + hi) / 2; int cnt = 0; cnt += sortAndCount(a, aux, lo, mid); cnt += sortAndCount(a, aux, mid + 1, hi); cnt += mergeAndCount(a, aux, lo, mid, hi); return cnt; } public static int inversionCount(int[] a) { int[] aux = new int[a.length]; return sortAndCount(a, aux, 0, a.length - 1); } public static void main (String[] args) { Scanner scan = new Scanner(System.in); int T = scan.nextInt(); while (T-- > 0) { int N = scan.nextInt(); int[] a = new int[N]; for (int i = 0; i < N; i++) { a[i] = scan.nextInt(); } System.out.println(inversionCount(a)); } }}
- 逆序数个数 (Inversion Counting) - Merge and Sort
- Merge Sort and Inversion
- Merge Sort and count inversion
- Merge Sort 并且返回逆序数的算法 - C#实现
- 归并排序(Merge Sort)+计算数列逆序数
- Inversion Sequence 已知逆序数(前面比它大的数的个数),还原数组
- hdu1394Minimum Inversion Number逆序数
- Inversion count implemented with merge sort
- Insertion Sort and Merge Sort
- Insertion sort and Merge sort
- Insertion Sort and Merge Sort
- HDU1394 Minimum Inversion Number 求逆序数
- 逆序数Sicily 5142. Inversion Number
- FZOJ 2166 inversion 逆序数对 模拟
- hdu 4911 Inversion (逆序数变换)
- hdu 4911 Inversion(求逆序数)
- 利用归并求逆序数 Inversion
- HDU1394 Minimum Inversion Number【逆序数】
- 高级查询简介
- 第一篇博客文章
- Java 项目启动流程
- 开发中的一些细小问题总结---字,字节,位,字符等
- Node.JS 环境搭建
- 逆序数个数 (Inversion Counting) - Merge and Sort
- 划分vlan,配置地址池
- 排序算法
- 文件读写
- UVa 12034 Race
- Android静默安装实现方案
- 第三周 项目4 顺序表的应用
- Swift 3.0 中的新变化
- Hibernate 多对多环境配置