使用并归排序,类似于小合问题,不过排序是从大到小排
//新建一个和片段长度相同的辅助数组
//在两段都不越界的情况下左右指针大小进行比较,取左右两边较大的一个并拷贝进新数组
//由于左右两段在之前已经分别进行从大到小的排序,故当左部分的数进入新数组时,必定大于右部分指针之后所有的数,逆序对增加计数
//当左右两边指针数字相同时加入右边的,不会产生逆序数计数
//当有一个越界时,把不越界的剩余元素添加到新数组
//新数组覆盖排序的数组,完成范围内的从大到小排列
class Solution {
public int reversePairs(int[] nums) {
return mergeSort(nums,0,nums.length-1);
}
public int mergeSort(int[] nums,int L,int R){
if(L>=R){
return 0;
}
int mid=L+((R-L)>>1);//位运算算中值
return mergeSort(nums,L,mid)+
mergeSort(nums,mid+1,R)+merge(nums,L,mid,R);
}
public static int merge(int []arr,int L,int M, int R ){
int []help=new int[R-L+1];
int i=0;
int p1=L;//左指针
int p2=M+1;//右指针
int sum=0;
while(p1<=M && p2<=R){
sum+=arr[p1]>arr[p2]?R-p2+1:0;//dang左边的数大于右边时,加上右指针比之小的个数
help[i++]=arr[p1]>arr[p2]?arr[p1++]:arr[p2++];//这里是总体的左大右小排序
}
while(p1<=M){//一边越界之后,将剩余元素加入到临时数组中,以下两个while只会进入一个
help[i++]=arr[p1++];
}
while(p2<=R){
help[i++]=arr[p2++];
}
for (int j = 0; j < help.length; j++) {
arr[L+j] = help[j];//将有序的覆盖原有的
}
return sum;
}
}