JZ35-数组中的逆序对
题目:在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数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
解题思路:使用归并排序的思想,归并排序不懂点这里查看归并排序详解;本题使用归并排序举例比如[6,3,1,4],可以看成[[6,3],[1,4]],当前6比1,4大,3比1大,共有3对,排序之后[[3,6],[1,4]],3比1大,同时6也肯定比1大,接下来6比4大,也是3对,结果都是一样的。
排序的好处就是当前数比较完之后,后面的数不用和比较过的再比,一定会比之前比较过得大。
代码看这里,相对于归并排序主要修改的是32-34行,记录逆序对数量。
public class Solution {
public int InversePairs(int [] array) {
return mergeSort(array, 0, array.length - 1, new int[array.length]);
}
/**
* 归并排序私有的处理方法
* @author 枫叶火火
* @param arr 数组
* @param first 第一个坐标
* @param last 最后一个坐标
* @param temp 临时数组
*/
private int mergeSort(int[] arr, int first, int last, int[] temp) {
if (first >= last) {
return 0;
}
int count = 0;//保存当前统计的逆序对数量
// 将arr看成两块
int i = first; // 块1的第一个坐标
int j = first + (last - first) / 2; // 块1的最后一个坐标
int m = j + 1; // 块2的第一个坐标
int n = last; // 块2的最后一个坐标
int k = 0; // 临时数组坐标
count += mergeSort(arr, i, j, temp); // 递归处理块1
count += mergeSort(arr, m, n, temp); // 递归处理块2
// 对有序的块1和块2进行合并
while (i <= j && m <= n) { // 当两块数组都有值时
if (arr[i] <= arr[m]) { // 将小的先填入临时数组
temp[k++] = arr[i++];
} else {
temp[k++] = arr[m++];
//修改归并排序,进行计数
count += (j-i+1); //如果i已经比比较的数字大,那么i之后到j的数字也一定比当前比较的数字大
count %= 1000000007;
}
}
while (i <= j) { // 如果第1块还有剩余填入临时数组
temp[k++] = arr[i++];
}
while (m <= n) { // 如果第2块还有剩余填入临时数组
temp[k++] = arr[m++];
}
// 将两块数组替换成排序好的一块
for (int ii = 0; ii < k; ii++) {
arr[first + ii] = temp[ii];
}
return count;
}
}