思路:使用归并排序思想,将array分为两部分,分别计算count,然后两部分归并统计。
需要注意的点:
1. 归并统计过程,可以使用两种思路:(1)对于第一部分每一个值,从第二部分二分查找比它大的元素下标,下标之前的元素数量计入统计值;(2)从两个部分的末尾开始比对(数组升序),对于第一部分的一个元素,若在第二部分中顺序找到比它小的元素,则该元素及其之前的元素数量计入统计值。
2.归并过程中仍然需要排序,也就是说,提取某一部分的逆序对统计值后,该部分就已经有序。
3.题目提示了数组容量,因此在统计值变化的步骤,都需要对统计值取模,避免int型的count统计量被加爆。
代码:
public int mergeCount(int[] array,int start1,int end1,int start2,int end2){
if(array==null||array.length==0||end1<start1||end2<start2) return 0;
//变量区
int totalLength=(end1-start1+1)+(end2-start2+1);
int[] bufStore=new int[totalLength];
int pointer1=end1,pointer2=end2,pointer3=totalLength-1;
int count=0;
//归并排序
while(pointer1>=start1&&pointer2>=start2){
while(pointer1>=start1&&array[pointer1]>array[pointer2]){
bufStore[pointer3--]=array[pointer1--];
//若array[pointer1]>array[pointer2],统计逆序数量
count+=(pointer2-start2+1);
count%=1000000007;//注意取模
}
if(pointer1<start1) break;
while(pointer2>=start2&&array[pointer1]<=array[pointer2]){
bufStore[pointer3--]=array[pointer2--];
}
if(pointer2<start2) break;
}
if(pointer1>=start1) {
for(int i=pointer1;i>=start1;i--){
bufStore[pointer3--]=array[i];
}
}
if(pointer2>=start2) {
for(int i=pointer2;i>=start2;i--){
bufStore[pointer3--]=array[i];
}
}
pointer1=start1;pointer2=start2;
for(int i=0;i<totalLength;i++){
if(i<(end1-start1+1)) array[pointer1++]=bufStore[i];
if(i>=(end1-start1+1)) array[pointer2++]=bufStore[i];
}
return count;
}
public int mergeSortCount(int [] array,int start,int end) {
if(array==null||array.length==0||start>=end) return 0;
int middle=(start+end)/2;
int leftPartCount=mergeSortCount(array,start,middle)%1000000007;
int rightPartCount=mergeSortCount(array,middle+1,end)%1000000007;
int combineCount=mergeCount(array,start,middle,middle+1,end)%1000000007;
return (leftPartCount+rightPartCount+combineCount)%1000000007;
}
public int InversePairs(int [] array) {
if(array==null||array.length==0) return 0;
return mergeSortCount(array,0,array.length-1)%1000000007;
}