目录
1.升序(以右边的合并组为基准)
2.降序(以左边的合并组为基准)
3.逆对序--固定下标
1.升序(以右边的合并组为基准)
找出左边有多少个数比我(nums[right])大
- 应该在每一次合并之前,进行逆序对查找
- 每一个该合并的组都是按升序排列,所以当nums[left]<nums[right]时,应该left++,因为都是升序,所以当nums[left]>nums[right],right++时,left从当前位置不动。
class Solution {
public:vector<int> ret;int vim=0;int reversePairs(vector<int>& record) {ret.resize(record.size());mergesort(record,0,record.size()-1);return vim;}void merge(vector<int>&nums,int low,int high,int mid){int left=low,right=mid+1, i=0;while(left<=mid&&right<=high){if(nums[left]<=nums[right]) ret[i++]=nums[left++];else {ret[i++]=nums[right++];vim+=(mid+1-left);}}while(left<=mid) ret[i++]=nums[left++];while(right<=high) ret[i++]=nums[right++];for(int i=0;i<high-low+1;i++){nums[i+low]=ret[i];}}void mergesort(vector<int>&nums,int low,int high){if(low>=high) return;int mid=(low+high)/2;mergesort(nums,low,mid);mergesort(nums,mid+1,high);merge(nums,low,high,mid);}
};
2.降序(以左边的合并组为基准)
找出多少个数比我小
合并过程:
class Solution {
public:vector<int> ret;int vim=0;int reversePairs(vector<int>& record) {ret.resize(record.size());mergesort(record,0,record.size()-1);return vim;}void merge(vector<int>&nums,int low,int high,int mid){int left=low,right=mid+1, i=0;while(left<=mid&&right<=high){if(nums[left]>nums[right]) {vim+=(high-right+1);ret[i++]=nums[left++];}else {ret[i++]=nums[right++];}}while(left<=mid) ret[i++]=nums[left++];while(right<=high) ret[i++]=nums[right++];for(int i=0;i<high-low+1;i++){nums[i+low]=ret[i];}}void mergesort(vector<int>&nums,int low,int high){if(low>=high) return;int mid=(low+high)/2;mergesort(nums,low,mid);mergesort(nums,mid+1,high);merge(nums,low,high,mid);}
};
对比:
降序 升序 void merge(vector<int>&nums,int low,int high,int mid)
{
int left=low,right=mid+1, i=0;
while(left<=mid&&right<=high)
{
if(nums[left]>nums[right])
{
vim+=(high-right+1);
ret[i++]=nums[left++];
}
else
ret[i++]=nums[right++];}
while(left<=mid) ret[i++]=nums[left++];
while(right<=high) ret[i++]=nums[right++];
for(int i=0;i<high-low+1;i++)
{
nums[i+low]=ret[i];
}
}void merge(vector<int>&nums,int low,int high,int mid)
{
int left=low,right=mid+1, i=0;
while(left<=mid&&right<=high)
{
if(nums[left]<=nums[right]) ret[i++]=nums[left++];
else
{
ret[i++]=nums[right++];
vim+=(mid+1-left);
}
}
while(left<=mid) ret[i++]=nums[left++];
while(right<=high) ret[i++]=nums[right++];
for(int i=0;i<high-low+1;i++)
{
nums[i+low]=ret[i];
}
}
3.逆对序--固定下标
增加一个下标数据,和交换下标数组,当交换数组发生数据交换时,交换下标数组也要发生数据交换
class Solution {vector<int> tempnums,index,tempindex,count;
public:vector<int> countSmaller(vector<int>& nums) {int n=nums.size();tempnums.resize(n);//交换数组tempindex.resize(n);//交换下标index.resize(n);//存放原始下表count.resize(n);//存放结果for(int i=0;i<n;i++) index[i]=i;mergesort(nums,0,n-1);return count;}void merge(vector<int>&nums,int low,int high,int mid){int left=low,right=mid+1,i=0;while(left<=mid&&right<=high){if(nums[left]>nums[right]) {tempnums[i]=nums[left];tempindex[i]=index[left];count[index[left]]+=(high-right+1);i++;left++;}else{tempindex[i]=index[right];tempnums[i]=nums[right];i++;right++;}}while(left<=mid){tempnums[i]=nums[left];tempindex[i]=index[left];i++;left++;}while(right<=high){tempindex[i]=index[right];tempnums[i]=nums[right];i++;right++;}for(int j=0;j<i;j++){nums[j+low]=tempnums[j];index[j+low]=tempindex[j];}}void mergesort(vector<int>&nums,int low,int high){if(low>=high) return ;int mid=(low+high)>>1;mergesort(nums,low,mid);mergesort(nums,mid+1,high);merge(nums,low,high,mid);}
};