Given an array nums
, we call (i, j)
an important reverse pair if i < j
and nums[i] > 2*nums[j]
.
You need to return the number of important reverse pairs in the given array.
Example1:
Input: [1,3,2,3,1] Output: 2
Example2:
Input: [2,4,3,5,1] Output: 3
Note:
- The length of the given array will not exceed
50,000
. - All the numbers in the input array are in the range of 32-bit integer.
/*
基于分治算法的思想,在归并排序的基础上寻找Reverse Pairs, 步骤如下:
1.递归划分序列;
2.对将要两两归并的子序列进行Reverse Pairs查找,假设两个子序列分别为a1,a2,统计Reverse Pairs个数count;
3.归并a1,a2,得到新的有子序列,重复步骤2,3,直到得到长度与原序列相同的有序序列,返回count.
Reverse Pairs查找方法如下:
假设将要归并的两个子序列是a1,a2;下标i,j分别为a1,a2的下标,由于序列进行的是归并排序,因此必有i<j,即表示a1,a2各自记录的顺序不影响查找Reverse Pairs,
对a1进行遍历,将a1的记录与a2中的记录进行比较,若满足a1[i]>a2[j]*2.0,则成功查找到Rever Pairs,子序列a2后移一位,继续和a1[i]比较.要注意到,
只要a1中较小的记录满足查找Reverse Pairs的准则,排在该记录后的所有记录都会满足该准则,因此,不必将a1的每个记录都与a2中的所有记录进行比较.
Reverse Pairs个数count的统计,我们只需要在遍历a1时对a2当前记录的下标j与a2第一个记录的下标之差进行累加即可.
*/
void merge(int* A,int* B,int low,int high){
int i,j,mid,k;
mid=(low+high)/2;
for(i=low;i<=high;++i)
B[i]=A[i];
for( k=low,i=low,j=mid+1;i<=mid&&j<=high;++k){
if(B[i]>B[j])
A[k]=B[j++];
else
A[k]=B[i++];
}
while(i<=mid)
A[k++]=B[i++];
while(j<=high)
A[k++]=B[j++];
}
int mergeSort(int* A,int* B,int low,int high){
int count = 0;
if(low<high){
int mid=high+low;
mid/=2;
count = mergeSort(A,B,low,mid)+mergeSort(A,B,mid+1,high);
for(int i = low,j=mid+1;i<=mid;++i){
while(j<=high&&A[i]>A[j]*2.0)j++;//查找Reverse Pairs
count+=j - mid - 1;//统计Reverse Pairs个数
}
merge(A,B,low,high);
}
return count;
}
int reversePairs(int* nums, int numsSize) {
int count = 0;
int* B = (int*)malloc(sizeof(int)*(numsSize));
count = mergeSort(nums,B,0,numsSize-1);//将nums的记录按从小到大的顺序进行归并排序
free(B);
B=NULL;
return count;
}