题目描述
在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数P。并将P对1000000007取模的结果输出。 即输出P%1000000007
输入描述:
题目保证输入的数组中没有的相同的数字
数据范围:
对于%50的数据,size<=10^4
对于%75的数据,size<=10^5
对于%100的数据,size<=2*10^5
示例1:
输入
1,2,3,4,5,7,0
输出
7
思路:
做的差点怀疑人生,唉,卡了好久,看到这题我先试了选择排序,一直成功率是百分之50,后来才知道,是数字超过上限了,也是醉了。然后尝试了归并排序,归并排序写起来不太难,之前也写过,不过还是没把这个和答案联系起来,看网上的也看晕了,可能还是太急躁,不过最后还是做出来了。
这个版本算是好理解的版本了,这里的num就是最后答案,这里的累加就在比较的时候,比如含有两组有序数列比较
[2,4,6,8,10,1,3,5,7,9]; 这里 left = 0 ; right = 9, 计算 mid = 4, 我们拿 a[1] = 4,举例,跟 a[6]=3比较,如果 a[1]>a[6],那肯定a[1]到 a[mid] (即a[4]) 的数都大于a[6],这里的个数就是 middle-i+1;
利用这个公式就能放入归并排序计算
class Solution {
public:
int InversePairs(vector<int> data) {
if(data.empty())
return 0;
vector<int> m = data;
int num=0;
MyMerge(data,m,0,data.size()-1,num);
return num;
}
void MyMerge(vector<int>&a, vector<int>&tmp,int start,int end,int &num)
{
if(start<end)
{
int mid = (start+end)/2;
MyMerge(a,tmp,start,mid,num);
MyMerge(a,tmp,mid+1,end,num);
merge(a,tmp,start,mid,end,num);
}
}
void merge(vector<int>&arr, vector<int>&m, int left,int middle,int right,int &num)
{
int i = left, j =middle+1, k = left;
while(i < middle+1 && j < right+1){
if(arr[i]<arr[j])
m[k++] = arr[i++];
else{
m[k++] = arr[j++];
num+=middle-i+1;
num=num>1000000007?num%1000000007:num;
}
}
if(i == middle+1){
while(j <right+1)
m[k++] = arr[j++];
}
else{
while(i < middle+1)
m[k++] = arr[i++];
}
while(left<= right){
arr[left] = m[left];
left ++;
}
}
};