Author: Zhai Tianbao Steven
Copyright statement: The copyright belongs to the author. For commercial reprint, please contact the author for authorization. For non-commercial reprint, please indicate the source
Title description:
Two numbers in the array, if the previous number is greater than the following number, the two numbers form a reverse pair. Enter an array and find the total number P of reversed pairs in this array. And output the result of P modulo 1000000007. That is, the output P mod 1000000007
data range: For 50% of the data, size≤104
For 100% of the data, size≤105
The values of all numbers in the array satisfy 0≤val≤109
Requirements: space complexity O(n), time complexity O(nlogn)
Example:
enter:
[1,2,3,4,5,6,7,0]
return value:
7
Problem-solving ideas:
The conventional solution to this question is the violent method, but this question requires a complexity of nlogn, so it can be solved by merge sort.
- Write a merge sort normally.
- In the process of merging and sorting combined sorting, the data of the two subintervals will be compared in turn to reconstruct the new order; at this time, if the value A on the left is greater than the value B on the right, then you can directly transfer the number of data from A to the middle position C Add directly. Because the subintervals have been sorted, since A is greater than B, all the data between A and C must also be greater than B, so a reverse order pair can be formed.
- In this way, the time complexity meets the requirements of the topic.
Test code:
class Solution {
public:
int mod = 1000000007;
// 归并排序
int mergeSort(vector<int>& data, int left, int right){
// 停止
if(left >= right)
return 0;
// 中间位
int mid = (left + right) / 2;
// 拆分合并,累加逆序对数量
int count = mergeSort(data, left, mid) + mergeSort(data, mid + 1, right);
count %= mod;
// 排序
int i = left, j = mid + 1;
vector<int> temp(data);
for(int t = left; t <= right; ++t){
// i如果到了mid+1,说明左子区间遍历完毕,后续直接取右区间数据即可
if(i == mid + 1){
data[t] = temp[j];
j++;
}
// j如果到了right+1,说明右子区间遍历完毕,后续直接取左区间数据即可
// 如果左侧值小于右侧值,不符合逆序对,正常排序即可
else if(j == right + 1 || temp[i] <= temp[j]){
data[t] = temp[i];
i++;
}
// 如果左侧值大于右侧值,说明左侧当前位置到左子区间结束的数值,都大于该右侧值,直接计算数量:mid-i+1;然后正常排序
// 这样操作降低了时间复杂度
else{
data[t] = temp[j];
j++;
count += mid - i + 1;
}
}
return count % mod;
}
// 逆序对
int InversePairs(vector<int>& nums) {
int size = static_cast<int>(nums.size());
int count = mergeSort(nums, 0, size - 1);
return count;
}
};