劍指offer:JZ35 陣列中的逆序對
阿新 • • 發佈:2020-12-17
技術標籤:劍指offer
題目描述
在陣列中的兩個數字,如果前面一個數字大於後面的數字,則這兩個數字組成一個逆序對。輸入一個數組,求出這個陣列中的逆序對的總數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
程式碼:
public class Solution {
int sum = 0;
public int InversePairs (int[] array) {
if (array == null || array.length == 0) {
return 0;
}
mergeSort(array, 0, array.length - 1);
return sum;
}
private void mergeSort(int[] arr, int l, int r) {
if (l == r) {
return;
}
int mid = l + (r - l) / 2;
mergeSort(arr, l, mid);
mergeSort(arr, mid + 1, r);
merge(arr, l, mid, r);
}
private void merge(int[] arr, int l, int mid, int r) {
int p1 = l;
int p2 = mid + 1;
int[] temp = new int[r - l + 1];
int idx = 0;
for (int i = l; i <= r; i++) {
if (p1 > mid) {
temp[idx++] = arr[p2++];
} else if (p2 > r) {
temp[idx++] = arr[p1++];
sum += (r - mid);
sum %= 1000000007;
} else if (arr[p1] <= arr[p2]) {
temp[idx++] = arr[p1++];
sum += (p2 - mid - 1);
sum %= 1000000007;
} else {
temp[idx++] = arr[p2++];
}
}
for (int i = 0; i < temp.length; i++) {
arr[l + i] = temp[i];
}
}
}
思路概述:
利用歸併的思想,判斷前半部分元素比後半部分元素大的個數。重點是在歸併過程中怎麼記錄。
第一個if:
if (p1 > mid) {
temp[idx++] = arr[p2++];
}
p1指標指向的前半部分元素已經遍歷完成,代表前半部分的元素不會比p2指標之後的元素大,此時只需要正常記錄元素即可
第二個if:
if (p2 > r) {
temp[idx++] = arr[p1++];
sum += (r - mid);
sum %= 1000000007;
}
此時p2指向的後半部分遍歷完成,代表所有p1指標的後位置的元素都大於後半部分元素,所以每遍歷一次加一遍後半部分元素的個數(p2-mid)
第三個if:
if (arr[p1] <= arr[p2]) {
temp[idx++] = arr[p1++];
sum += (p2 - mid - 1);
sum %= 1000000007;
}
此時p2是後半部分第一個大於p1對應元素,所以此時比p1小的元素的個數為(p2 - mid - 1)
最後一個if:
if (arr[p1] > arr[p2]) {
temp[idx++] = arr[p2++];
}
此時正常的移動指標即可,找到第一個大於p1對應元素的位置,再通過上一個if計算。