剑指offer面试题51:数组中的逆序对

Posted chsobin

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了剑指offer面试题51:数组中的逆序对相关的知识,希望对你有一定的参考价值。

题目

* 面试题51:数组中的逆序对
* 在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。
* 输入一个数组,求出这个数组中的逆序对的总数P。
* 并将P对1000000007取模的结果输出。 即输出P%1000000007

思路

1、暴力 ,时间复杂度O(n^2)

2、归并排序的思路 :时间复杂度O(nlogn)

* (1) 先将数组分成两半,递归分别计算左半边的逆序对数目leftCnt 和右半边的逆序对数目rightCnt
* (2)再计算合并之后新增的逆序对数目cnt

注意:
* left + right + cnt 有可能超过int,因此中间结果用long存储,最后再转化为int

代码

技术图片
 1 public class P51 {
 2      // 归并排序 的变形
 3     private long mergeSort(int[] datas, int[] copy, int start, int end){
 4         if(start == end) return 0;
 5         int mid = (start + end)/2;
 6         long leftCnt = mergeSort(datas, copy, start, mid)%1000000007;// 左边的逆序对数目
 7         long rightCnt = mergeSort(datas, copy, mid+1, end)%1000000007; // 右边的逆序对数目
 8         
 9         long cnt = 0;    // 合并之后,新增的逆序对数目
10         int index = start;    // copy数组的下标
11         int i = start;    // 左半边 数组起始下标
12         int j = mid+1;    // 右半边 数组起始下标
13         
14         // 该变量记录当左半边某个数datas[i]插入copy数组中,右半边已经插入copy数组中的数目
15         int rightSmallICnt = 0;    
16         
17         // 合并数组,合并的时候计算逆序对数目
18         while(i<=mid && j<=end){
19             if(datas[i]<=datas[j]){
20                 copy[index++] = datas[i];
21                 i++;
22                 cnt += rightSmallICnt;
23             }else{
24                 copy[index++] = datas[j];
25                 j++;
26                 rightSmallICnt++;    // 记录右半边数组中右多少个元素 已经插入到copy数组中 
27             }
28         }
29         if(i>mid){
30             while(j<=end){
31                 copy[index++] = datas[j++];    
32             }
33         }else{
34             while(i<=mid){
35                 copy[index++] = datas[i++];
36                 cnt += rightSmallICnt;
37             }
38         }
39         
40         // 复制回原数组 
41         for(int k=start;k<=end;++k) datas[k] = copy[k];
42         return (leftCnt + rightCnt + cnt)%1000000007;
43     }
44     
45     // 统计逆序对数目
46     public int InversePairs(int [] array) {
47         if(array==null || array.length<=1) return 0;    // 对输入数据进行处理
48         int[] copy = new int[array.length];                // 辅助数组
49         return (int)mergeSort(array, copy, 0, array.length-1);
50     }
51     
52     // 测试
53     public static void main(String[] args) {
54         int[] array = new int[]{5,6,7,8, 1, 2, 3, 4};
55         int ans = new P51().InversePairs(array);
56         System.out.println(ans);
57     }
58 }
View Code

 

以上是关于剑指offer面试题51:数组中的逆序对的主要内容,如果未能解决你的问题,请参考以下文章

剑指Offer---面试题36:数组中的逆序对

剑指offer面试题36-数组中的逆序对

《剑指offer》第五十一题(数组中的逆序对)

剑指Offer对答如流系列 - 数组中的逆序对

[剑指offer]51-数组中的逆序对(归并排序)

剑指offer-36:数组中的逆序对