1. 程式人生 > 其它 >劍指offer:JZ35 陣列中的逆序對

劍指offer:JZ35 陣列中的逆序對

技術標籤:劍指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計算。