剑指offer35:数组中的逆序对

Posted wxwhnu

tags:

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

1 题目描述

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

2 思路和方法

  利用归并排序的思想,先把数组分隔成子数组,先统计出子数组内部的逆序对的数目,然后再统计出两个相邻子数组之间的逆序对的数目。注意在合并两个已排序的子数组后,要更新数组。O(n*log(n))。

技术图片

 

3 C++核心代码

技术图片
 1 class Solution 
 2 public:
 3     int InversePairs(vector<int> data) 
 4         if(data.size() <= 1)
 5             return 0;
 6         int count = 0;
 7         vector<int> copy(data); // 初始化
 8         InversePairsCore(data, copy, 0, data.size()-1,count);
 9         return count;
10     
11 
12     // 归并
13     void InversePairsCore(vector<int> &data, vector<int> &copy, int start, int end, int &count)
14         if(start>=end)
15             return;
16         
17         int mid = (start + end) /2;
18         InversePairsCore(data,copy,start,mid,count);
19         InversePairsCore(data,copy,mid+1,end,count);
20 
21         int copyIndex = end; // 将较大数字从后往前复制到辅助数组
22         int i = mid;    // 前半段最后一个元素下标
23         int j = end;    // 后半段最后一个元素下标
24         while (i>=start && j>=mid+1) 
25             if (data[j] < data[i])     // 逆序
26                 count += j - mid;
27                 count %= 1000000007;    // 取模防止逆序对溢出
28                 copy[copyIndex--] = data[i--];
29              else
30                 copy[copyIndex--] = data[j--];
31             
32         
33 
34         while (i>=start)
35             copy[copyIndex--] = data[i--];
36 
37         while (j>=mid+1)
38             copy[copyIndex--] = data[j--];
39 
40         for (int k = start; k <= end; ++k)
41             data[k] = copy[k];
42 
43     
44 ;
View Code

4 C++完整代码

技术图片
 1 #include<iostream>
 2 using namespace std;
 3 //数组中的逆序对
 4 long long GetMergePairsBetween(int* arr,int* copy,int start,int mid,int end)
 5 
 6     //合并两个子数组,并计算逆序对个数
 7     int final1 = mid;//第一个数组的最后一位
 8     int final2 = end;//第二个数组的最后一位
 9     int index = end;//辅助数组的最后一位
10     long long count = 0;
11     while(final1 >= start && final2 >= mid+1)//两个数组都没有处理完
12     
13        if(arr[final1] > arr[final2])
14        
15            //如果第一个数组的元素大于第二个数组的任何元素,
16            //则第一个数组的元素一定大于第个数组中final2之前的所有元素
17            count += (final2 - mid);
18            //将final1处的元素拷贝至copy数组
19            //index和final1都向前移动
20            copy[index--] = arr[final1--];
21        
22        else
23        
24            //第一个数组的元素小于第二个数组的元素
25            //第二个数组的元素拷贝至copy数组
26            //并将index和final2前移
27            copy[index--] = arr[final2--];
28        
29     
30     while(final1 >= start)//第一个数组的元素没有处理完
31     
32        copy[index--] = arr[final1--];
33     
34     while(final2 >= mid + 1)//第一个数组的元素没有处理完
35     
36        copy[index--] = arr[final2--];
37     
38     for(int i = end; i > index;i--) 
39         arr[i] = copy[i];
40     return count;
41 
42 long long GetMergePairs(int* arr,int* copy,int start,int end)
43 
44     long long ret = 0;
45     if(start < end)
46     
47        int mid = start + ((end - start)>>1);
48        ret += GetMergePairs(arr,copy,start,mid);
49        ret += GetMergePairs(arr,copy,mid+1,end);
50        ret += GetMergePairsBetween(arr,copy,start,mid,end);
51     
52     return ret;
53 
54 long long GetTotalPairs(int arr[],int n)
55 
56     if(arr == NULL || n < 2)
57        return 0;
58     int* copy = new int[n];
59     long long sum = GetMergePairs(arr,copy,0,n-1);
60     delete[] copy;
61     return sum;
62 
63 int main()
64 
65     int arr[] = 7,5,6,4;
66     int ret = GetTotalPairs(arr,sizeof(arr)/sizeof(arr[0]));
67     cout<<ret<<endl;
68     system("pause");
69     return 0;
70 
View Code

参考资料

https://blog.csdn.net/zjwreal/article/details/88769617

https://blog.csdn.net/DERRANTCM/article/details/46761051(图)

https://blog.csdn.net/peiyao456/article/details/54645952(完整代码)

 

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

剑指offer35:数组中的逆序对

剑指offer[35]——数组中的逆序对

剑指Offer35:数组中的逆序对

[剑指Offer] 35.数组中的逆序对

剑指offer系列——35.数组中的逆序对??

[剑指offer] 35. 数组中的逆序对