描述
在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数P。并将P对1000000007取模的结果输出。 即输出P mod 1000000007
数据范围: 对于50% 的数据, size ≤ 10^4
对于100% 的数据 size ≤ 10^5数组中所有数字的值满足 0 ≤ val ≤ 10^9
要求:空间复杂度O(n),时间复杂度 O(nlogn)
输入描述:
题目保证输入的数组中没有的相同的数字
示例1
输入:
[1,2,3,4,5,6,7,0]
返回值:
7
示例2
输入:
[1,2,3]
返回值:
0
解决方法:
通过冒泡排序,一个数字前面有几个大于它的数,等于它从小到大排序向前移动了几位,也就是冒泡的次数。因为是顺序冒泡,所以前面已经冒泡过的小数或相同数不会干扰当前数字的冒泡次数,所以找逆序对次数的问题就转换成了升序排序冒泡次数的问题。
public int InversePairs(int [] array) {
if (array == null || array.length == 0 || array.length == 1) {
return 0;
}
int total = 0;
for (int i = 1; i < array.length; i++) {
if (array[i] < array[i-1]) {
total += popSort(array, i);
total %= 1000000007;
}
}
return total;
}
public int popSort(int[] nums, int pos) {
int temp;
int total = 0;
while (pos > 0 && nums[pos] < nums[pos-1]) {
temp = nums[pos];
nums[pos] = nums[pos-1];
nums[pos-1] = temp;
total++;
pos--;
}
return total;
}
优化:冒泡排序太慢了,整体时间复杂度为 O(N^2) ,所以需要对冒泡进行优化,所以可以采用二分排序来优化这一过程,使时间复杂度下降到 O(NlogN)。
public int InversePairs(int [] array) {
if (array == null || array.length == 0 || array.length == 1) {
return 0;
}
return dcSort(array, 0, array.length-1, new int[array.length]);
}
// 递归排序
public int dcSort(int[] array, int start, int end, int[] temp) {
if (start >= end) {
temp[0] = array[start];
return 0;
}
int total = 0;
int mid = (start + end) / 2;
int[] left = new int[mid - start + 1];
int[] right = new int[end - mid];
total += dcSort(array, start, mid, left);
total %= 1000000007;
total += dcSort(array, mid+1, end, right);
total %= 1000000007;
total += mergeArray(temp, left, right);
total %= 1000000007;
return total;
}
// 合并左右时计算逆序对个数
public int mergeArray(int[] result, int[] left, int[] right) {
int pos = 0;
int lLen = left.length;
int total = 0;
int lPos = 0;
int rPos = 0;
while (lPos < left.length && rPos < right.length) {
if (left[lPos] > right[rPos]) {
result[pos] = right[rPos];
rPos++;
total += (lLen - lPos);
pos++;
} else {
result[pos++] = left[lPos++];
}
}
while (lPos < left.length) {
result[pos++] = left[lPos++];
}
while (rPos < right.length) {
result[pos++] = right[rPos++];
}
return total;
}