参考博客:https://www.cnblogs.com/wanglei5205/p/8893700.html
题目描述:
在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数P。并将P对1000000007取模的结果输出。 即输出P%1000000007
输入描述:
题目保证输入的数组中没有的相同的数字
数据范围:
对于%50的数据,size<=10^4
对于%75的数据,size<=10^5
对于%100的数据,size<=2*10^5
思路:
基于归并排序的思想统计逆序对:先把数组分割成子数组,再子数组合并的过程中统计逆序对的数目。统计逆序对时,先统计子数组内部的逆序对的数目,再统计相邻子数组的逆序对数目。
利用归并排序:比如 9 5 7 4把长度为4的数组分解成长度为2的分组,把长度为2的数组分解成长度为1的数组->95 74 ->9 5 7 4
合并排序->59 74 ->4579主要的算法在merge里面 因为合并排序后的数据比如:6789 2345。。。6大于2则6789均大于2,cnt+=4;6大于3则6789均大于3,cnt+=4;6大于3则6789均大于3,cnt+=4;6大于4则6789均大于4,cnt+=4;
详见代码:
#include
#include
using namespace std;
int cnt = 0;
void merge(vector<int>& data, int start, int mid, int end)
{
vector<int> tmp; //tmp临时变量用来存储当前[start,end]段排序后的结果,然后再赋值给data
int i = start, j = mid + 1; //采用的是引用传递,所以修改的是原数组
while (i <= mid&&j <= end)
{
if (data[i] > data[j]) //6789 2345 6大于2 那么cnt+=4 tmp.push_back(2)
{
cnt = (cnt + mid - i + 1) % 1000000007; ///对1000000007取余是为了防止整形溢出
tmp.push_back(data[j++]);
}
else
tmp.push_back(data[i++]); //6789 10 11 12 13 6小于10 那么tmp.push_back(6)
} //tmp就是存data(start,end)区间内从小到大的存储起来
while (i <= mid) {
tmp.push_back(data[i++]);//待合并排序的数据比如6789 2345那么这个循环执行的就是
//tmp.push_back(7)tmp.push_back(8)tmp.push_back(9)
}
while (j <=end) {
tmp.push_back(data[j++]);
}
for (int i = 0; i < tmp.size(); ++i)
{
data[start + i] = tmp[i];
}
}
void mergesort(vector<int>& data, int start, int end) //分解
{
if (start < end)
{
int mid = (start + end) >> 1;
mergesort(data, start, mid );
mergesort(data, mid+1,end);
merge(data, start, mid, end); //调用归并排序的合并排序函数
}
}
int InversePairs(vector<int> data) {
int n = data.size();
if (n != 0)
{
mergesort(data, 0, n - 1); //调用归并排序的分解函数
}
return cnt;
}
void main()
{
vector<int> data = {
364, 637, 341, 406, 747, 995, 234, 971, 571, 219, 993, 407, 416, 366, 315, 301, 601, 650, 418, 355, 460, 505, 360, 965, 516, 648, 727, 667, 465, 849, 455, 181, 486, 149, 588, 233, 144, 174, 557, 67, 746, 550, 474, 162, 268, 142, 463, 221, 882, 576, 604, 739, 288, 569, 256, 936, 275, 401, 497, 82, 935, 983, 583, 523, 697, 478, 147, 795, 380, 973, 958, 115, 773, 870, 259, 655, 446, 863, 735, 784, 3, 671, 433, 630, 425, 930, 64, 266, 235, 187, 284, 665, 874, 80, 45, 848, 38, 811, 267, 575 };
//答案为:2519
//vector data = { 1,2,3,4,5,6,7,0 };
//答案为:7
//vector data = { 5,3,1,4,2 };
//答案为:7
cout << InversePairs(data) << endl;
cin.get();
return;
}