题目1：排序数组

``````class Solution {
public:
void merge(vector<int>& nums, int begin, int mid, int end, vector<int>& tmp) {
int leftbegin = begin;
int rightbegin = mid + 1;
int tmpbegin = begin;

while (leftbegin <= mid && rightbegin <= end) {
//这里需要一个tmp数组来帮助我们再排序完数组之后将数组返回到原数组
if (nums[leftbegin] < nums[rightbegin]) {
tmp[tmpbegin++] = nums[leftbegin++];
} else {
tmp[tmpbegin++] = nums[rightbegin++];
}
}

while (leftbegin <= mid) {
tmp[tmpbegin++] = nums[leftbegin++];
}

while (rightbegin <= end) {
tmp[tmpbegin++] = nums[rightbegin++];
}

for (int i = begin; i <= end; i++) {
nums[i] = tmp[i];
}
}

void mergeSort(vector<int>& nums, int begin, int end, vector<int>& tmp) {
//这一个函数地目的便是不断地将数组进行二分
if (begin >= end) {
return;
}

int mid = (begin + end) / 2;
mergeSort(nums, begin, mid, tmp);
mergeSort(nums, mid + 1, end, tmp);
merge(nums, begin, mid, end, tmp);//二分完之后这个函数地目的为对函数进行合并
}

vector<int> sortArray(vector<int>& nums) {
vector<int> tmp(nums.size());
mergeSort(nums, 0, nums.size() - 1, tmp);
return tmp;
}
};``````

题目2：数组中的逆序对

``````class Solution {
public:
//这一个版本为左右数组中的元素为降序的情况
void find_same(vector<int>& nums,vector<int>& tmp,int begin,int mid,int end,int& ret)
{
int leftbegin = begin;
int rightbegin = mid+1;
int tmpi = begin;//作为tmp数组的下标
while(leftbegin<=mid&&rightbegin<=end)
{

if(nums[leftbegin]<=nums[rightbegin])
{
tmp[tmpi++] = nums[rightbegin++];
}
//当找到一个rightbegin中对应的数是比leftbegin小的话，从rightbegin开始到end这一段的所有数都是比leftbegin小的
else//在这里是rightbegin>leftbegin
{
tmp[tmpi++] = nums[leftbegin];
ret+= end - rightbegin+1;//找到了此时大于rightbegin的所有的数目的个数，此时这些数的个数也就是好数对的数目
leftbegin++;
}
}
while(leftbegin<=mid)
{
tmp[tmpi++] = nums[leftbegin++];
}
while(rightbegin<=end)
{
tmp[tmpi++] = nums[rightbegin++];
}
//最后要将这道题给排序完成
for(int i = begin;i<=end;i++)
{
nums[i] = tmp[i];
}
}
void _reversePairs(vector<int>& nums,vector<int>& tmp,int begin,int end,int& ret)
{
if(begin>=end)
{
return;
}
int mid = (begin+end)/2;
_reversePairs(nums,tmp,begin,mid,ret);
_reversePairs(nums,tmp,mid+1,end,ret);//将数组分成两个部分
//第三个部分合并的同时要统计逆序对的数目
find_same(nums,tmp,begin,mid,end,ret);//合并并且去寻找逆序对
}//
int reversePairs(vector<int>& nums) {
//题目思路和归并排序的思路很相似
int ret = 0;//统计逆序对的数目
vector<int> tmp(50010);//创建一个临时数组
_reversePairs(nums,tmp,0,nums.size()-1,ret);
return ret;
}
};//这里我使用了一个ret去储存逆序对的数目``````

题目2：计算右侧小于当前元素的个数

``````class Solution {
public:
void merge_sort(vector<int>& nums,int begin,int end,vector<int>& tmp1,vector<int>& tmp2,vector<int>& ret,vector<int>& index)
{
if(begin>=end)
{
return ;
}//确定递归的返回条件
int mid = (begin+end)>>1;
merge_sort(nums,begin,mid,tmp1,tmp2,ret,index);//分治左半部分并且完成排序
merge_sort(nums,mid+1,end,tmp1,tmp2,ret,index);//分治右半部分并且完成排序
//下面再来进行合并
//这里的tmp2数组就是为了确保index数组里面的元素能够和nums数组一样的进行移动
//而做的临时数组
int leftbegin = begin;
int rightbegin = mid+1;
int tmp1i = begin;
int tmp2i = begin;//作为tmp1和tmp2数组的下标
while(leftbegin<=mid&&rightbegin<=end)
{
if(nums[leftbegin]<=nums[rightbegin])
{
tmp1[tmp1i++] = nums[rightbegin];
tmp2[tmp2i++] = index[rightbegin++];
}
else
{
tmp1[tmp1i++] = nums[leftbegin];
tmp2[tmp2i++] = index[leftbegin];
ret[index[leftbegin]] += end - rightbegin+1;
leftbegin++;
}
}
while(leftbegin<=mid)
{
tmp1[tmp1i++] = nums[leftbegin];
tmp2[tmp2i++] = index[leftbegin++];//同时要更新的是一个和nums绑定的数组
}
while(rightbegin<=end)
{
tmp1[tmp1i++] =nums[rightbegin];
tmp2[tmp2i++] = index[rightbegin++];
}
//最后要合并数组
for(int i = begin;i<=end;i++)
{
nums[i] = tmp1[i];
index[i] = tmp2[i];
}
}
vector<int> countSmaller(vector<int>& nums) {
vector<int> index(nums.size());//创建一个数组这个数组中的每一个数都代表了nums中的每一个数的下标
for(int i = 0;i<nums.size();i++)
{
index[i] = i;//nums中的第i个数在nums中的下标
//index数组中的下标i代表的是nums中的第i个数（0代表第一个数）然后index里面储存的就是这个数在nums[i]中的下标
}
vector<int> ret(nums.size());//用于记录和返回答案的数组
//下面要使用
vector<int> tmp1(nums.size());//一个用于辅助index的合并
vector<int> tmp2(nums.size());//一个用于辅助nums的合并
merge_sort(nums,0,nums.size()-1,tmp1,tmp2,ret,index);
return ret;
}
};``````

``````class Solution {
public:
void _reversePairs(vector<int>& nums, vector<int>& tmp, int begin, int end, int& ret)
{
if (begin >= end)
{
return;
}//确定递归终止条件
int mid = (begin + end) >> 1;
_reversePairs(nums, tmp, begin, mid, ret);
_reversePairs(nums, tmp, mid + 1, end, ret);
//由此就将数组分成了两个部分，并且两个部分都已经把各自的逆序对给计算出来了
//下面需要先计算翻转对的数目，在进行合并，我这里使用的是降序
int leftbbegin = begin, rightbegin = mid + 1;
//由此就完成了降序状态下翻转对的计算
//这里要使用同向双指针
while (leftbbegin <= mid)
{
while (rightbegin <= end)
{
//因为题目给出的数据在乘上一个2倍之后可能会超出int的范围所以这里使用了/
if (nums[leftbbegin]/2.0 > nums[rightbegin])
{
ret += end - rightbegin + 1;
break;
}
else
{
rightbegin++;
}
}
leftbbegin++;
}
//下面要将两个部分的数组有序合并
int tmpi = begin;
leftbbegin = begin;
rightbegin = mid + 1;
while (leftbbegin <= mid && rightbegin <= end)
{
if (nums[leftbbegin] >= nums[rightbegin])
{
tmp[tmpi++] = nums[leftbbegin++];
}
else
{
tmp[tmpi++] = nums[rightbegin++];
}
}
while (leftbbegin <= mid)
{
tmp[tmpi++] = nums[leftbbegin++];
}
while (rightbegin <= end)
{
tmp[tmpi++] = nums[rightbegin++];
}
for (int i = begin; i <= end; i++)
{
nums[i] = tmp[i];
}
}
int reversePairs(vector<int>& nums) {
//思路为分治+同向双指针
vector<int> tmp(nums.size());//创建一个临时数组，用于合并两个分开的数组
int ret = 0;//记录翻转对的数目
_reversePairs(nums, tmp, 0, nums.size() - 1, ret);//寻找从0到nums.size()-1位置存在多少组翻转对
return ret;
}
};``````