/*
* 在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数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
*/
思路:其实就是进行一个归并排序的过程
例如:(4,2,6,1)
先分解成(4,2),(6,1)再分解成4,2,6,1已经是最小单元
对4,2进行归并,指针1指向4,指针2指向2,4>2,产生1对逆序对 count=1
同理,6,1产生1对逆序对 count=2
接下来对(2,4),(1,6)归并
指针1指向2,指针2指向1,2>1,那么显然左边的有序序列(2,4)中的所有元素都会比1大,产生了左边序列长度个逆序对,此处为2个,此时count=4
然后指针2后移指向6,显然2<6,不产生逆序对,然后指针1后移指向4,4<6不产生逆序对,这时归并也结束了得到(1,2,4,6),count=4
所以整个方法是建立在归并排序上的。下面附上代码
public class Solution {
static int count=0;
public static int InversePairs(int [] array) {
if(array.length==0)
return 0;
mysort(array);
return count%1000000007;
}
public static int[] mysort(int[] a) //为归并排序写的统一接口
{
if(a.length==0)
return null;
return sort(a,0,a.length-1);
}
private static int[] sort(int[] a,int left,int right) //递归解决归并
{
int mid=(left+right)/2;
if(left<right)
{
sort(a,left,mid);
sort(a,mid+1,right);
guibing(a,left,mid,right);
}
return a;
}
private static int[] guibing(int[] a,int left,int mid,int right) //归并两个有序序列
{
int i=left;
int j=mid+1;
int k=0;
int[] temp=new int[right-left+1];
while(i<mid+1&&j<=right)
{
if(a[i]<=a[j])
{
temp[k++]=a[i++];
}
else
{
temp[k++]=a[j++];
count+=mid-i+1;
count=count%1000000007;//除去此处count相关代码就是完完全全的归并排序
}
}
while(i<mid+1)
{
temp[k++]=a[i++];
}
while(j<=right)
{
temp[k++]=a[j++];
}
k--;
while(true)
{
a[right--]=temp[k--];
if(k<0)
break;
}
return a;
}
}