解題思路
分治法:
採用的就是歸併函數中的分治思想,該題與分治排序的不同點在於,在治的過程中進行逆序對的統計,逆序對的個數爲
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];
}
}
};