1. 程式人生 > 其它 >BM20 陣列中的逆序對

BM20 陣列中的逆序對

連結:https://www.nowcoder.com/practice/96bd6684e04a44eb80e6a68efc0ec6c5

本題採用歸併排序的思想對問題進行求解,即在每次遞迴歸併中,對遞迴出的子問題考慮能組成逆序對的個數,來以此累加。

解題程式碼:

 1 static int mod = (int) (1e9 + 7);
 2     //逆序對問題
 3     public int InversePairs(int [] array) {
 4         if (array == null ||array.length == 1 ) {
 5             return 0;
6 } 7 return process(array,0,array.length - 1) % mod; 8 } 9 10 public int process(int[] array,int l,int r) { 11 if (l == r) { 12 return 0; 13 } 14 int mid = l + ((r - l) >> 1); 15 return (process(array,l,mid) + process(array,mid + 1,r) + merge(array,l,mid,r)) % mod;
16 } 17 18 public int merge(int[] array,int l,int mid,int r) { 19 int ans = 0; 20 int i = l, j = mid + 1; 21 int[] help = new int[r - l + 1]; 22 int cnt = 0; 23 while (i <= mid && j <= r) { 24 if (array[i] > array[j]) { 25
ans += r - j + 1; 26 help[cnt++] = array[i++]; 27 } 28 else { 29 help[cnt++] = array[j++]; 30 } 31 } 32 while (i <= mid) { 33 help[cnt++] = array[i++]; 34 } 35 while (j <= r) { 36 help[cnt++] = array[j++]; 37 } 38 for (int k = 0; k < r - l + 1; k++) { 39 array[k + l] = help[k]; 40 } 41 return ans % mod; 42 }

 

還可以借鑑這道題的思路:

 1 /*利用歸併排序思想,求解部分最小和的問題
 2      * 如arr = {1,3,4,2,5} ,則對於1來說左側沒有比1小的數,所以和為0
 3      *                           對於3來說左側有個1比3小,所以和為1
 4      *                          對於4來說左側有個1和3比4小,所以和為4
 5      *                           對於2來說左側有個1比2小,所以和為1
 6      *                         對於5來說左側有1,3,4,2比5小,所以和為10   所以總和為16
 7      */
 8     /*
 9      * 可以換一種思路進行求解:
10      * 1.對於第一個1,之後有3,4,2,5四個數都比它大,所以共要加4次
11      * 2.對於第二個3,之後有4,5兩個數都比它大,所以共要加2次
12      * 3.按照這個思路以此類推至最後一個元素
13      * 
14      * 所以可以沿用歸併排序的思想,每次歸併時,如果左邊的數比右邊的數小,則加上一次左邊的這個數
15      */
16     
17     public static int MergeAll(int[] arr)
18     {
19         if (arr == null || arr.length == 1) {
20             return 0;
21         }
22         return process(arr,0,arr.length - 1);
23     }
24     
25     public static int process(int[] arr,int l,int r)
26     {
27         if (l == r) {
28             return 0;
29         }
30         int mid = l + ((r - l) >> 1);
31         
32         return process(arr,l,mid) + process(arr,mid + 1,r) + Merge(arr,l,mid,r);
33     }
34     
35     public static int Merge(int[] arr,int l,int mid,int r)
36     {
37         int ans = 0;
38         int i = l, j = mid + 1;
39         int[] help = new int[r - l + 1];
40         int cnt = 0;
41         while (i <= mid && j <= r) {
42             if (arr[i] < arr[j]) {
43                 ans += arr[i] * (r - j + 1);
44                 help[cnt++] = arr[i++];
45             }
46             else {
47                 help[cnt++] = arr[j++];
48             }
49         }
50         while (i <= mid) {
51             help[cnt++] = arr[i++];
52         }
53         while (j <= r) {
54             help[cnt++] = arr[j++];
55         }
56         for (int k = 0; k < r - l + 1; k++) {
57             arr[k + l] = help[k];
58         }
59         return ans;
60     }