BM20 数组中的逆序对
中等 通过率:16.61% 时间限制:3秒 空间限制:256M
知识点数组
描述
在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数P。并将P对1000000007取模的结果输出。 即输出P mod 1000000007
数据范围: 对于 50% 的数据, size≤104
对于 100% 的数据, size≤105
数组中所有数字的值满足 0≤val≤109
要求:空间复杂度 O(n),时间复杂度 O(nlogn)
输入描述:
题目保证输入的数组中没有的相同的数字
示例1
1 2
| 输入:[1,2,3,4,5,6,7,0] 返回值:7
|
示例2
题解
暴力方法:
按住一个arr[i], 依次判断{i+1 … n-1]是否满足条件。n为数组的大小,对于10^5数据,O(N^2)算法显然超时。
归并排序思想:
可以参考:排序——归并排序(Merge sort)-CSDN博客
归并排序的过程,主要有以下两个操作:
- 递归划分整个区间为基本相等的左右两个区间
- 合并两个有序区间
主函数
1 2 3 4 5 6 7 8 9 10 11 12 13
|
int InversePairs(vector<int>& nums) { int ret = 0; vector<int> tmp(nums.size());
mergeSort(nums, tmp, 0, nums.size()-1, ret); return ret; }
|
递归划分整个区间
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
|
void mergeSort(vector<int> &arr, vector<int> &tmp, int l, int r, int& ret){ if(l >= r){ return; } int mid = l + ((r - l) >> 1); mergeSort(arr, tmp, l, mid, ret); mergeSort(arr, tmp, mid+1, r, ret); merge(arr, tmp, l, mid, r, ret); }
|
合并两个有序区间
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| void merge(vector<int> &arr, vector<int> &tmp, int l, int mid, int r, int& ret){ int i = l, j = mid + 1, k = 0; while(i <= mid && j <= r){ if(arr[i] > arr[j]){ ret += (mid + 1 - i); ret %= kmod; tmp[k++] = arr[j++]; }else{ tmp[k++] = arr[i++]; } }
while(i <= mid){ tmp[k++] = arr[i++]; } while(j <= r){ tmp[k++] = arr[j++]; }
for(k = 0, i = l; i <= r; i++, k++){ arr[i] = tmp[k]; } }
|
时间复杂度:O(NlogN)
空间复杂度:O(N)