一、解题思路:
每个数去找左边比自己大的数的个数,找到后进行加和。
二、关键过程:
在归并排序的过程中在每次递归的过程中数组会被持续分成若干个两组,当递归回来时,右边在归并时检测左组还剩下的个数,即大于右组数的个数(小于右侧的已经归并完成了),右组归并时不检测(因为对于左组来说,没有左边的数)。
三、 关键问题:
问:一组求完后该组就被排好序了,那么排序会影响求和吗?
答:不会!因为对于下一组来说上一组的左右都属于左组(或右组)。
问:排序的意义?
答:确定比右组大的数的操作是O(1)。
五、注意事项:
当左右两组merge时若是相同,则先归并左组方便右组确定大于其的个数。
六、 示例代码:
public static int reversePair(int arr[]){
if(arr == null || arr.length < 2){
return 0;
}
return process(arr, 0, arr.length - 1);
}
private static int process(int arr[], int left, int right){
if(left == right){
return 0;
}
int mid = left + ((right - left) >> 1);
return process(arr, left, mid) + process(arr, mid + 1, right)
+ merge(arr, left, right, mid);
}
private static int merge(int arr[], int left, int right, int mid){
int N = right - left + 1;
int help[] = new int[N]; int k = 0;
int p1 = left; int p2 = mid + 1;
int cnt = 0;
while (p1 <= mid && p2 <= right){
if(arr[p1] <= arr[p2]){
help[k++] = arr[p1++];
}else{
cnt += mid - p1 + 1;
help[k++] = arr[p2++];
}
}
while(p1 <= mid){
help[k++] = arr[p1++];
}
while(p2 <= right){
help[k++] = arr[p2++];
}
for(int i = 0; i < N; i++){
arr[left++] = help[i];
}
return cnt;
}