逆序对定义:在一个数组a[]中,i和j分别为数组的下标,其中i < j,如果a[i]>a[j],则a[i]和a[j]是一对逆序对。
思路:利用归并排序的思想,先求前面一半数组的逆序数,再求后面一半数组的逆序数,然后求前面一半数组比后面一半数组中大的数的个数(也就是逆序数),这三个过程加起来就是整体的逆序数目了。
代码:
public class Solution {
public int inversePairs(int[] array) {
if(array == null || array.length == 0)
return 0;
int[] copy = new int[array.length]; // 辅助数组
for(int i = 0; i < array.length; i++) {
copy[i] = array[i];
}
int count = inversePairsCore(array, copy, 0, array.length - 1);
return count;
}
private int inversePairsCore(int[] array, int[] copy, int low, int high) {
if(low < high) {
int mid = (low + high) / 2;
int leftCount = inversePairsCore(array, copy, low, mid);
int rightCount = inversePairsCore(array, copy, mid+1, high);
int count = 0; // 计算数目
int i = mid; // 左边数目
int j = high; // 右边数目
int copyIndex = high; // 辅助数组的索引
// 左右两部分都是从后往前计算
while(i >= low && j > mid) {
if(array[i] > array[j]) {
count += j-mid;
copy[copyIndex--] = array[i--];
} else {
copy[copyIndex--] = array[j--];
}
}
//添加可能剩下的前半部分到copy中
for(; i >= low; i--) {
copy[copyIndex--] = array[i];
}
//添加可能剩下的后半部分到copy中
for(; j > mid; j--) {
copy[copyIndex--] = array[j];
}
// 将排好序的copy复制到array中
for(int v = low; v <= high; v++) {
array[v] = copy[v];
}
return (leftCount + rightCount + count);
}
return 0;
}
}