描述
在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数P。并将P对1000000007取模的结果输出。 即输出P mod 1000000007
数据范围: 对于 50\%50% 的数据, size\leq 10^4size≤104
对于 100\%100% 的数据, size\leq 10^5size≤105
数组中所有数字的值满足 0 \le val \le 10000000≤val≤1000000
要求:空间复杂度 O(n)O(n),时间复杂度 O(nlogn)O(nlogn)
输入描述:
题目保证输入的数组中没有的相同的数字
示例1
输入:
[1,2,3,4,5,6,7,0]复制
返回值:
7复制
示例2
输入:
[1,2,3]复制
返回值:
0复制
1、首先想到的是暴力解法,但是暴力解法的时间复杂度是O(N*N),不符合题目要求;
2、O(nlogn)的时间复杂度一般是二分查找,本题中不是查找最优解,儿时统计逆序对个数;
3、仔细分析题意,找逆序对的过程可以用归并排序的过程来实现;
4、先将无序数组递归的二分为一个一个的数,再通过比较大小的方式将单个的数一块一块并起来,再并的过程中排序,同时统计逆序个数;
5、需要特别注意的是,merge函数中,已经可以认为左右区间已经分别有序,从左右的其实点开始遍历时,若遇到逆序对,那么对于左区间上其余值来说也一定是逆序对;
class Solution {
public:
// 暴力解法会超时
/*int InversePairs(vector<int> data) {
int n = data.size();
int res = 0;
for (int i = n - 1; i > 0; i--) {
for (int j = 0; j < i; j++) {
if (data[j] > data[i]) {
res++;
if (res == 1000000007) res = 0;
}
}
}
return res;
}*/
int merge(vector<int> &data, int left, int mid, int right, vector<int> &tmp) {
// 左半区未排序元素索引
int l_pos = left;
// 右半区未排序元素索引
int r_pos = mid + 1;
// 临时数组索引
int pos = left;
int res = 0;
// 合并
// 此时的左右部分已经分别有序了
while (l_pos <= mid && r_pos <= right) {
if (data[l_pos] > data[r_pos]) {
tmp[pos++] = data[r_pos++];
//res++;
// 出现左侧大于右侧的情况后,左侧索引之后的所有数字肯定都是大于右侧当前数字的。故需要加的是左侧从当前索引开始到最后位置的数字个数,同时右侧索引移到下一位
res += mid + 1 - l_pos;
res = res % 1000000007;
} else {
tmp[pos++] = data[l_pos++];
}
}
while (l_pos <= mid) {
tmp[pos++] = data[l_pos++];
}
while (r_pos <= right) {
tmp[pos++] = data[r_pos++];
}
for (int i = left; i <= right; i++) {
data[i] = tmp[i];
}
return res;
}
// 计算left到right之间有几个逆序对
int div(vector<int> &data, int left, int right, vector<int> &tmp) {
int mid = (right - left) / 2 + left;
int res = 0;
if (left >= right) {
return res;
}
res += div(data, left, mid, tmp);
res = res % 1000000007;
res += div(data, mid+1, right, tmp);
res = res % 1000000007;
res += merge(data, left, mid, right, tmp);
res = res % 1000000007;
return res;
}
int InversePairs(vector<int> data) {
int n = data.size();
int res = 0;
if (n < 2) return 0;
vector<int> tmp(n);
res = div(data, 0, n-1, tmp);
return res;
}
};

京公网安备 11010502036488号