解题思路
分治法:
采用的就是归并函数中的分治思想,该题与分治排序的不同点在于,在治的过程中进行逆序对的统计,逆序对的个数为
cnt += center - i + 1;
这也是在归并排序上要加的代码
代码
/*
思路:分治
通过分的方式,获得每个子区间,在合并每个子区间时计算每个子区间内部的逆序对个数
*/
#include<iostream>
#include <vector>
using std::vector;
class Solution {
int cnt = 0;
public:
int reversePairs(vector<int>& nums) {
if (nums.size() < 2) return 0;//特判,size为0,1不可能出现逆序对
vector<int> temps(nums.size());
mergeSort(nums, temps, 0, nums.size() - 1);
return cnt;
}
//归并排序
void mergeSort(vector<int>& nums, vector<int>& temps, int left, int right) {
if (left < right) {
int center = left + (right - left) / 2;
mergeSort(nums, temps, left, center);//左分
mergeSort(nums, temps, center + 1, right);//右分
merge(nums, temps, left, center, right);//治
}
}
//合并
void merge(vector<int>& nums, vector<int>& temp, int left, int center, int right) {
int i = left, j = center + 1;
for (int k = left; k <= right; k++) {
if (i > center) {//左边的已经比较完,将右边的全部放到temp中
temp[k] = nums[j++];
}
else if (j > right) {//右边的已经比较完,将左边的全部放到temp中
temp[k] = nums[i++];
}
else if (nums[i] > nums[j]) {//左边大于右边,出现逆序对,
temp[k] = nums[j++];//取右边数组值
cnt += center - i + 1;//此处+1是因为center是等于right的,这里也是比归并排序多的一行代码
}
else//左边小于等于右边
{
temp[k] = nums[i++];//取左边数组值
}
}
//将temp中的元素复制到nums中
for (int k = left; k <= right; k++) {
nums[k] = temp[k];
}
}
};