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++) {//此处是help数组的长度,而不是array数组的长度
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     }
复制代码

 

posted @   jue1e0  阅读(36)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
点击右上角即可分享
微信分享提示