So here is O(n log n) solution in java.
long merge(int[] arr, int[] left, int[] right) {
int i = 0, j = 0, count = 0;
while (i < left.length || j < right.length) {
if (i == left.length) {
arr[i+j] = right[j];
j++;
} else if (j == right.length) {
arr[i+j] = left[i];
i++;
} else if (left[i] <= right[j]) {
arr[i+j] = left[i];
i++;
} else {
arr[i+j] = right[j];
count += left.length-i;
j++;
}
}
return count;
}
long invCount(int[] arr) {
if (arr.length < 2)
return 0;
int m = (arr.length + 1) / 2;
int left[] = Arrays.copyOfRange(arr, 0, m);
int right[] = Arrays.copyOfRange(arr, m, arr.length);
return invCount(left) + invCount(right) + merge(arr, left, right);
}
This is almost normal merge sort, the whole magic is hidden in merge function.
Note that while sorting algorithm remove inversions.
While merging algorithm counts number of removed inversions (sorted out one might say).
The only moment when inversions are removed is when algorithm takes element from the right side of an array and merge it to the main array.
The number of inversions removed by this operation is the number of elements left from the the left array to be merged. :)
Hope it's explanatory enough.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…