题目描述
在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数P。并将P对1000000007取模的结果输出。 即输出P%1000000007
输入例子:
1,2,3,4,5,6,7,0
输出例子:
7
解题思路
- 利用归并排序
- 空间换时间
- 单次归并中逆序对的计算公式为
- 当P1指向的数字大于P2指向的数字,表明数组中存在逆序对。P2指向的数字在第二个子数组的位置,决定了以排好序的子数组中,所有P2前面(包括P2指向数字)的数字都比P1小。
count = j(P2指针位置)-start-mid
Java实现
public class Solution {
public int InversePairs(int [] array) {
if (array == null || array.length == 0)
return 0;
int[] copy = new int[array.length];
/*
arraycopy(Object src,
int srcPos,
Object dest,
int destPos,
int length)
src:源数组; srcPos:源数组要复制的起始位置;
dest:目的数组; destPos:目的数组放置的起始位置; length:复制的长度。
*/
System.arraycopy(array, 0, copy, 0, array.length);
int count = InversePairsCore(array, copy, 0, array.length-1);
return count;
}
private int InversePairsCore(int[] array, int[] copy, int low, int high){
//递归终止条件
if (low == high)
return 0;
//递归
int mid = low + ((high - low) >> 1);
int leftCount = InversePairsCore(array, copy, low, mid) % 1000000007;
int rightCount = InversePairsCore(array, copy, mid+1, high) % 1000000007;
//归并排序,计算逆序对数
int count = 0;
int i = mid;
int j = high;
int locCopy = high;
while(i >= low && j > mid){
if (array[i] > array[j]){
count += j - mid;
copy[locCopy--] = array[i--];
if (count >= 1000000007)
count %= 1000000007;
}else{
copy[locCopy--] = array[j--];
}
}
//若 j< mid后,复制剩余i值
for (; i >= low; i--)
copy[locCopy--] = array[i];
//若 i< start后,复制剩余j值
for (; j > mid; j--)
copy[locCopy--] = array[j];
//copy到源数组
for (int s = low; s <= high; s++)
array[s] = copy[s];
return (leftCount+rightCount+count)%1000000007;
}
}