剑指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> ©, 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 ;
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
参考资料
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:数组中的逆序对的主要内容,如果未能解决你的问题,请参考以下文章