题目描述:
有一组数,对于其中任意两个数组,若前面一个大于后面一个数字,则这两个数字组成一个逆序对。请设计一个高效的算法,计算给定数组中的逆序对个数。
给定一个int数组A和它的大小n,请返回A中的逆序对个数。保证n小于等于5000。
测试样例:
[1,2,3,4,5,6,7,0],8
返回:7
思路:参考剑指offer,采用归并的排序法
代码是我在牛客网oj环境下编译通过的:
class AntiOrder {
public:
int count(vector<int> A, int n) {
// write code here
if(A.size()==0||n==0)
{
return 0;
}
vector<int> copy(n,0);
for(int i=0;i<n;i++)
{
copy[i]=A[i];
}
int count=countCode(A,copy,0,n-1);
return count;
}
int countCode(vector<int>& data,vector<int>& copy,int start,int end)
{
if(start==end)
{
copy[start]=data[start];
return 0;
}
int length=(end-start)/2;
int left=countCode(copy,data,start,start+length);
int right=countCode(copy,data,start+length+1,end);
//初始化i为前半段最后一个数字的下标
int i=length+start;
//初始化j为后半段最后一个数字的下标
int j=end;
int indexCopy=end;
int count=0;//用于计数
while(i>=start&&j>=start+length+1)//判断逆序对的终止条件
{
if(data[i]>data[j])//如果前半段p1大于p2,p1向前移动,并且将p1拷贝到p3
{
copy[indexCopy--]=data[i--];
count+=j-start-length;//计数
}else//p1<=p2,则p2向前移动,并拷贝p2到p3
{
copy[indexCopy--]=data[j--];
}
}
for(;i>=start;--i)
{
copy[indexCopy--]=data[i];
}
for(;j>=start+length+1;--j)
{
copy[indexCopy--]=data[j];
}
return left+right+count;
}
};