方法:归并排序
题目中要求得出一个数组的所有逆序对(前面的数大于后面的数组成一个逆序对),归并排序将数组向下拆分至单个元素的数组,然后向上递归,不断地合并两个数组,直到将整个数组完成排序。
如果是两个有序的数组,我们就可以很容易得到该元素逆序对的数目,而不用一个个进行遍历比较。
时间复杂度: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; } };