题目描述
在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数P。并将P对1000000007取模的结果输出。 即输出P%1000000007
因为测试数据的结果会特别大,所以需要取余
##示例1
输入
1,2,3,4,5,6,7,0
输出
7
##思路
分治的思想(归并排序):把数据递归划分成前后两个数组(直到每个数组仅有一个数据项),然后进行数组的合并(两个数组在内部已经是有序了的,按照从小到大的顺序)。合并数组时,出现前面的数组值array[i]大于后面数组值array[j]时,则前面数组array[i]都是大于后面数组中array[mid] ~ array[j]的,count += j - mid,并在两个数组合并过程中进行排序,使得两个数组合并后有序(正序,从小到大排列)。
整体代码实现和二路归并排序很相似。
代码实现(Java)
public static int InversePairs(int [] array) {
if(array == null || array.length == 0) return 0;
int[] copy = new int[array.length]; //辅助数组,归并排序也需要
return InversePairsCore(array, copy, 0, array.length - 1);
}
private static int InversePairsCore(int[] array, int [] copy, int low, int high){
if(low == high) return 0; //划分为仅有一个数据项
int mid = (low + high) >> 1;
int leftCount = InversePairsCore(array, copy, low, mid) % 1000000007;
int rightCount = InversePairsCore(array, copy, mid + 1, high) % 1000000007;
int count = 0;
int i = mid;//两个子数组,[low, mid] 和 [mid + 1, high]
int j = high;
int copyIndex = high; //把两个有序数组合并为一个有序数组,下标的移动,从右往左
while(i >= low && j > mid){
if(array[i] > array[j]) { //存在逆序对
count += j - mid; //逆序对累加
copy[copyIndex--] = array[i--]; //合并数组操作
if(count >= 1000000007) count %= 1000000007;
}
else copy[copyIndex--] = array[j--]; //不存在逆序对也要进行合并数组操作
}
for(;i >= low;i--) copy[copyIndex--] = array[i];//对两个数组剩余部分进行合并数组操作
for(;j > mid;j--) copy[copyIndex--] = array[j];
for(int k = low;k <= high;k++) array[k] = copy[k]; //将合并后的数组copy到原数组
return (leftCount + rightCount + count) % 1000000007;
}
题目,思路及代码均来源于牛客网–剑指offer
本文介绍了一种利用归并排序思想解决数组中逆序对计数问题的方法。通过分治策略,将数组逐步分解再合并,同时计算逆序对数量,并确保结果对1000000007取模。此算法复杂度较低,适用于大数据场景。
723

被折叠的 条评论
为什么被折叠?



