在數組中的兩個數字,如果前面一個數字大於後面的數字,則這兩個數字組成一個逆序對,例如在數組{7,5,6,4}中,一共存在5對逆序對,分別是{7,6},{7,5},{7,4},{6,4},{5,4}。輸入一個數組,求出這個數組中的逆序對的總數P。並將P對1000000007取模的結果輸出。,即輸出P%1000000007。
代碼
解法一
暴力簡單低效,不會改變原數組
public static int inversePairs(int[] array) {
if (array == null || array.length < 2) {
return 0;
}
int count = 0;
for (int i = 0; i < array.length; i++) {
for (int j = i + 1; j < array.length; j++) {
if (array[i] > array[j]) {
count++;
}
}
}
return count % 1000000007;
}
解法二
利用數組的歸併排序,高效,但是會改變原數組
public static int inversePairs2(int[] array) {
if (array == null || array.length < 2) {
return 0;
}
int count = mergeSort(array, 0, array.length - 1);
return count % 1000000007;
}
private static int mergeSort(int[] array, int start, int end) {
if (start >= end) {
return 0;
}
// 找到數組的中點,分割爲兩個子數組,遞歸求解
int middle = (start + end) / 2;
int left = mergeSort(array, start, middle);
int right = mergeSort(array, middle + 1, end);
// 存儲歸併後的數組
int[] copy = new int[array.length];
System.arraycopy(array, start, copy, start, end - start + 1);
// 從兩個子數組的尾部開始遍歷
int i = middle;
int j = end;
int copyIndex = end;
// 記錄逆序對的數量
int count = 0;
while (i >= start && j >= middle + 1) {
// 數組是升序的
// 如果左邊數組比右邊數組大,則將大的放入存儲數組中
// 並且累加逆序對,應爲是有序的,所以左邊數組的第i個元素比第j個及其之前的數都大
if (array[i] > array[j]) {
copy[copyIndex--] = array[i--];
count += (j - middle);
} else {
copy[copyIndex--] = array[j--];
}
}
// 將子數組剩餘的部分一次寫入歸併後的存儲數組
while (i >= start) {
copy[copyIndex--] = array[i--];
}
while (j >= middle + 1) {
copy[copyIndex--] = array[j--];
}
// 將本次兩個子數組的合併寫入原數組中
for (int k = start; k <= end ; k++) {
array[k] = copy[k];
}
return left + right + count;
}