将数组划分为左右子数组,则逆序对总数=左区间内部逆序对+右区间内部逆序对数+左右区间之间的逆序对。思路类似求最大和子区间(max[左子区间最大和,右子区间最大和,中间子区间最大和])。
先将数组递归划分为子数组,再依次合并,合并时计算逆序对。注意左右两边不要重复计算,计算一边即可。
class Solution {
public:
int reversePairs(vector<int>& nums) {
int revNums=0;
merge(nums,0,nums.size()-1,revNums);
return revNums;
}
void merge(vector<int>& nums,int left,int right,int& revNums){
if(left>=right){return;}
int mid=(left+right)/2;
merge(nums,left,mid,revNums);
merge(nums,mid+1,right,revNums);
mergeSort(nums,left,right,revNums);
}
void mergeSort(vector<int>& nums,int left,int right,int& revNums){
int mid=(left+right)/2;
int r=mid+1,l=left;
vector<int> s;
while(l<=mid && r<=right){
if(nums[l]<=nums[r]){
s.push_back(nums[l++]);
}
else{
s.push_back(nums[r++]);
revNums+=(mid-l+1);
}
}
for(int k:s){
nums[left++]=k;
}
//注意此处不要重复计算逆序对
while(l<=mid){
s.push_back(nums[l++]);
}
while(r<=right){
s.push_back(nums[r++]);
}
}
};