题目:
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
Example:
The sequence 2, 4, 1, 3, 5 has three inversions (2, 1), (4, 1), (4, 3).
方法:
简单算法:两个循环,第二个指针从第一个指针的后面一个元素开始,比较大小,前面的大,结果加一,复杂度为O(n^2);
利用mergeSort的算法:merge过程中我们会判断前半部分和后半部分的元素大小,如果前半部分的元素大于后半部分,那么从当前这个前半部分的元素到中间元素的所有元素都满足inversion,因此结果加(mid+1-i),把结果融入递归,可解。
参考:
http://www.geeksforgeeks.org/counting-inversions/
Code:
import java.util.*;
class Test{
public static void main(String[] args){
Sort s = new Sort();
int[] a = {1, 2, 3, 4, 5, 6, 7};
int[] b = {2, 4, 1, 3, 5};
int[] aux = new int[a.length];
s.shuffle(a);
s.display(a);
System.out.println(s.mergeSort(a, aux, 0, a.length-1));
// System.out.println(s.mergeSort(b, aux, 0, b.length-1));
s.display(a);
}
}
class Sort{
public int mergeSort(int[] a, int[] aux, int head, int tail){
if(head == tail)
return 0;
int res = 0;
int mid = (head+tail)/2;
res += mergeSort(a, aux, head, mid);
res += mergeSort(a, aux, mid+1, tail);
res += merge(a, aux, head, mid, tail);
return res;
}
private int merge(int[] a, int[] aux, int head, int mid, int tail){
int res = 0, cnt = 0, i = head, j = mid+1;
while(i<=mid && j<=tail){
if(a[i] < a[j]) aux[cnt++] = a[i++];
else{
aux[cnt++] = a[j++];
res += mid + 1 - i;
}
}
while(i <= mid) aux[cnt++] = a[i++];
while(j <= tail) aux[cnt++] = a[j++];
for(int k=0; k<cnt; k++) a[k+head] = aux[k];
return res;
}
public void display(int[] a){
for(int i=0; i<a.length; i++)
System.out.print(a[i] + " ");
System.out.println();
System.out.println("-----------------------------------------------");
}
public void shuffle(int[] a){
Random rnd = new Random();
for(int i=0; i<a.length; i++)
swap(a, i, rnd.nextInt(a.length));
}
public void swap(int[] a, int i, int j){
int tmp = a[i];
a[i] = a[j];
a[j] = tmp;
}
}
小结:
方法二可以看做递归算法的巧妙运用。