【剑指offer】53.数组中的逆序对
总目录:
1.问题描述
在数组中的两个数字,如果前面任意一个数字大于后面的任意一个数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数P。并将P对1000000007取模的结果输出。
即输出P mod 1000000007,防止数字太大造成溢出
数据范围: 对于 50%的数据, size≤10^4
对于 100%100% 的数据, size≤10^5
数组中所有数字的值满足 0≤val≤10^9
题目保证输入的数组中没有的相同的数字
题目保证输入的数组中没有的相同的数字
要求:空间复杂度 O(n),时间复杂度 O(nlogn)
2.问题分析
1暴力迭代,略
2归并排序
归并排序的时间复杂度为O(nlogn),在归并排序时如果发现前面的数字比后面的数字大,则前面集合中剩余的所有数字都比后面这个数字大,累加记录
3.代码实例
归并排序中记录

1 class Solution { 2 public: 3 const int modPara = 1000000007; 4 int InversePairs(vector<int> data) { 5 //数据过少 6 int dataLen = data.size(); 7 if (dataLen < 2) { 8 return 0; 9 } 10 11 12 int ret = 0; 13 vector<int> tmp(dataLen); 14 merge_sort(data, tmp, 0, dataLen - 1, ret); 15 return ret; 16 } 17 18 void merge_sort(vector<int>& arr, vector<int>& tmp, int left, int right, 19 int& ret) { 20 if (left >= right) { 21 return; 22 } 23 24 int mid = left + ((right - left) >> 1); 25 merge_sort(arr, tmp, left, mid, ret); 26 merge_sort(arr, tmp, mid + 1, right, ret); 27 merge(arr, tmp, left, mid, right, ret); 28 } 29 30 void merge(vector<int>& arr, vector<int>& tmp, int left, int mid, int right, 31 int& ret) { 32 int i = left, j = mid + 1, k = 0; 33 34 //左右两侧的公共长度 35 while (i <= mid && j <= right) { 36 if (arr[i] <= arr[j]) {//前面的小于等于后面的 37 tmp[k++] = arr[i++]; 38 } else { //注意,前面的比后面的大 39 tmp[k++] = arr[j++]; 40 ret += (mid - i + 1);//左侧剩余都比右侧curVal大 41 ret %= modPara; 42 } 43 } 44 45 //左侧有剩余 46 while (i <= mid) { 47 tmp[k++] = arr[i++]; 48 } 49 50 //右侧有剩余 51 while (j <= right) { 52 tmp[k++] = arr[j++]; 53 } 54 55 //从tmp复制回arr 56 for (k = 0, i = left; i <= right; ++i, ++k) { 57 arr[i] = tmp[k]; 58 } 59 } 60 };