方法:归并排序
题目中要求得出一个数组的所有逆序对(前面的数大于后面的数组成一个逆序对),归并排序将数组向下拆分至单个元素的数组,然后向上递归,不断地合并两个数组,直到将整个数组完成排序。
如果是两个有序的数组,我们就可以很容易得到该元素逆序对的数目,而不用一个个进行遍历比较。
时间复杂度:o(nlogn)。递归的深度有logn层,每层需要遍历n个元素进行排序归并,所以时间复杂度为o(nlogn)。
空间复杂度:o(n)。数组需要一个o(n)的空间来保存排序后的数组,每层都需要o(n),一层排序合并完后可以释放掉该空间,所以虽然递归有logn层,但是只需要o(n)的空间。
class Solution {
public:
//归并排序
void merge(vector<int>& nums, vector<int>& temp, int left, int right,
int& ret) {
if (left >= right)
return;
//将数组从中间分为两个数组
int mid = (left + right) / 2;
//划分
merge(nums, temp, left, mid, ret);
merge(nums, temp, mid + 1, right, ret);
//排序合并
merge_sort(nums, temp, left, mid, right, ret);
}
void merge_sort(vector<int>& nums, vector<int>& temp, int left, int mid,
int right, int& ret) {
int l = left;
int r = mid + 1;
int k = 0;
int res = 1000000007;
while (l <= mid && r <= right) {
//当左侧数组有元素大于右侧数组的元素,可以得到该元素在这个数组的所有逆序对数目
if (nums[l] > nums[r]) {
temp[k++] = nums[r++];
//该元素在这个数组的所有逆序对数目
ret += (mid - l + 1);
ret %= res;
} else {
temp[k++] = nums[l++];
}
}
while (l <= mid)
temp[k++] = nums[l++];
while (r <= right)
temp[k++] = nums[r++];
for (k = 0, l = left; l <= right; k++, l++)
nums[l] = temp[k];
}
int InversePairs(vector<int>& nums) {
int ret = 0;
//数组的归并排序需要一个同样大小的数组来保存排序后的数组
vector<int> temp(nums.size());
merge(nums, temp, 0, nums.size() - 1, ret);
return ret;
}
};

京公网安备 11010502036488号