题目描述:
在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数P。并将P对1000000007取模的结果输出。 即输出P%1000000007。
思路:
方法1:最直观的方法,顺序扫描数组,每扫描到一个数字,再顺序扫描其后的每个数字,如果后面的数字比当前数字小,则组成一个逆序对。这种方法需要两层循环,O(n^2)的复杂度。
方法2:借鉴归并排序的思路
先把数组分隔为子数组,统计子数组内部的逆序对的数目,然后再统计两个相邻子数组之间的逆序对的数目。
注意:
a. 调用InversePairsCore时,因为要把上一次排好序的结果做合并,所以data和count需要交换,copy中的数组是排好序的,data是用来做合并的,也就是上一步在copy中排好的子数组,下一步要作为data进行合并操作放入copy中,如此交替,最后data和copy中的数字完全一样。
b. 因为在算子数组的count过程中可能就超过1000000007溢出了,所以对于每次count增加之后都要对1000000007取模。
(刚开始只在最后一步返回count的时候取模了,case通过率只有50%)
参考代码:
在线测试
AC代码
方法1:case通过率50%,对于很大的数组时间复杂度过高
class Solution {
public:
int InversePairs(vector<int> data) {
if(data.empty() || data.size()<2)
return 0;
int p=0;
for(int i=0; i<data.size();i++)
{
for(int j=i+1;j<data.size();j++)
{
if(data[j]<data[i])
p++;
}
}
p=p%1000000007;
return p;
}
};
方法2:
class Solution {
public:
int InversePairs(vector<int> data) {
if(data.empty()||data.size()<2)
return 0;
vector<int> copy(data);
int count = InversePairsCore(data,copy,0,data.size()-1);
return count%1000000007;
}
int InversePairsCore(vector<int> &data,vector<int> ©,int start,int end)
{
if(start==end)
{
copy[start]=data[start];
return 0;
}
int length=(end-start)/2;
int left=InversePairsCore(copy,data,start,start+length);
int right=InversePairsCore(copy,data,start+length+1,end);
int p1=start+length;
int p2=end;
int p3=end;
int count=0;
while(p1>=start && p2>=start+length+1)
{
if(data[p1]>data[p2])
{
copy[p3--]=data[p1--];
count = count + p2 - (start+length);
count = count%1000000007;
}
else
{
copy[p3--]=data[p2--];
}
}
while(p1>=start)
{
copy[p3--]=data[p1--];
}
while(p2>=start+length+1)
{
copy[p3--]=data[p2--];
}
return (left+right+count)%1000000007;
}
};