题目描述
在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数P。并将P对1000000007取模的结果输出。 即输出P%1000000007
输入描述:
题目保证输入的数组中没有的相同的数字
数据范围:
对于%50的数据,size<=10^4
对于%75的数据,size<=10^5
对于%100的数据,size<=2*10^5
示例1
输入
1,2,3,4,5,6,7,0
输出
7
解题思路:
分治问题,不断将数组一分为二,直到数组中只有两个元素,统计逆序对个数,分别排序后进行合并,merge的时候计算合并的两个数组间的逆序对个数。类似归并排序的过程
代码实现:
public class Solution {
/*
分治问题,不断将数组一分为二,直到数组中只有两个元素,统计逆序对个数,
分别排序后进行合并,merge的时候计算合并的两个数组间的逆序对个数。类似归并排序的过程
*/
int count=0;
public int InversePairs(int [] array) {
if(array==null||array.length<=0){
return 0;
}
mergeSort(array,0,array.length-1);
return count;
}
/*
归并排序
*/
public void mergeSort(int [] a,int start,int end){
if(start>=end)
return;
int mid=(end+start)>>1;
mergeSort(a,start,mid);
mergeSort(a,mid+1,end);
merge(a,start,mid,end);
}
/*
归并:将一个数组中的两个相邻有序区间合并成一个
*/
public void merge(int [] a,int start,int mid,int end){
int[] temp=new int[end-start+1];
int i=start,j=mid+1,index=0;
while(i<=mid && j<=end){
if(a[i]>a[j]) {//如果前面的元素大于后面的,那么在前面元素之后的元素都能和后面的元素构成逆序对
temp[index++]=a[j++];
//当前面的数组值a[i]大于后面数组值a[j]时;
//则前面数组a[i]~a[mid]多个元素都是大于array[j]的
count+=mid-i+1;
count=count>1000000007?count%1000000007:count;
}else{//如果前面的元素小于后面的不能构成逆序对
temp[index++]=a[i++];
}
}
while(i<=mid){
temp[index++]=a[i++];
}
while(j<=end){
temp[index++]=a[j++];
}
//将临时数组赋值给原数组
for(int k=0;k<temp.length;k++){
a[start+k]=temp[k];
}
}
}