题目:在数组中的两个数字如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数。在数组{7,5,6,4}中一共存在5对逆序对,分别是(7,6),(7,5),(7,4),(6,4),(5,4)。
最直观的解法:
最简单的想法就是遍历每一个元素,让其与后面的元素对比,如果大于则count++,但是这样的时间复杂度是o(n2)。
先把数组分解成两个长度为2的子数组,再把这两个子数组分解成两个长度为1的子数组。接下来一边合并相邻的子数组,一边统计逆序对的数目。在第一对长度为1的子数组{7}、{5}中7>5,因此(7,5)组成一个逆序对。同样在第二对长度为1的子数组{6},{4}中也有逆序对(6,4),由于已经统计了这两对子数组内部的逆序对,因此需要把这两对子数组进行排序,避免在之后的统计过程中重复统计
逆序对的总数=左边数组中的逆序对的数量+右边数组中逆序对的数量+左右结合成新的顺序数组时中出现的逆序对的数量;
public int InversePairs(int [] array) {
if(array==null||array.length==0)
{
return 0;
}
int[] copy = new int[array.length];
for(int i=0;i<array.length;i++)
{
copy[i] = array[i];
}
int count = InversePairsCore(array,copy,0,array.length-1);//数值过大求余
return count;
}
private int InversePairsCore(int[] array, int[] copy, int start, int end) {
if (start==end){
copy[start]=array[start];
return 0;
}
int length=(end-start)/2;
int left=InversePairsCore(copy,array,start,start+length);
int right=InversePairsCore(copy,array,start+length+1,end);
int i=start+length;
int j=end;
int indexCopy=end;
int count=0;
while (i>start&&j>=start+length+1){
if (array[i]>array[j]){
copy[indexCopy--]=array[i--];
count+=j-start-length;
}else {
copy[indexCopy--]=array[j--];
}
}
for (;i>=start;--i){
copy[indexCopy--]=array[i];
}
for (; j>=start+length+1;--j){
copy[indexCopy--]=array[j];
}
return left+right+count;
}
参考文章