题目链接
思路分析
第一种方法是进行穷举暴力解法,但这肯定会超时
因此我们可以不断划分区间,使用归并排序的思想,求解每一个小区间的逆序对,然后将它们加在一起,就能得到最终的结果,也就是总的逆序对数。
[1,3,6,9] [2, 5, 8]
对于3 5来说 3 < 5 但是3 大于 5之前的所有数,例如2
再对于6来说,尽管6 < 8 但是6 大于8之前的所有数
我们将这些数加起来,就是我们最终求解的逆序对数
代码实现
class Solution {
public:
int mergeSort(vector<int>& nums, vector<int>& arr, int start, int end)
{
if(start >= end)
return 0;
int mid = start + (end - start)/2;
int cnt = mergeSort(nums, arr, start, mid) + mergeSort(nums, arr, mid+1, end);
int left1 = start;
int right1 = mid;
int left2 = mid+1;
int right2 = end;
int index = start;
while(left1 <= right1 && left2 <= right2)
{
//如果left1 < left2 说明left1所在的位置的数值,均大于left2前面的数值
//[1,3,6,9] [2, 5, 8]
//对于3 5来说 3 < 5 但是3 大于 5之前的所有数
//这里要记住是 *****<=****一定要注意,如果是小于的话,就不会被计入次数
if(nums[left1] <= nums[left2])
{
arr[index] = nums[left1++];
cnt += (left2 - (mid +1));
}
else
arr[index] = nums[left2++];
index++;
}
//如果left1没有结束,则每一个都存在逆序对
while(left1 <= right1)
{
cnt += (left2 - (mid +1));
arr[index++] = nums[left1++];
}
while(left2 <= right2)
{
arr[index++] = nums[left2++];
}
for(int i = start; i <= end; ++i)
{
nums[i] = arr[i];
}
return cnt;
}
int reversePairs(vector<int>& nums) {
//使用归并排序的思想寻找逆序对
int cnt = 0;
vector<int> arr(nums.size());
cnt = mergeSort(nums, arr, 0, nums.size()-1);
return cnt;
}
};