题目描述:
Recall the problem of finding the number of inversions. As in the course, we are given a
sequence of n numbers a 1, · · · , a n, which we assume are all distinct, and we difine an inversion
to be a pair i < j such that a i > a j
We motivated the problem of counting inversions as a good measure of how different two
orderings are. However, one might feel that this measure is too sensitive. Let’s call a pair
a significant inversion if i < j and a i > 3a j. Given an O(n log n) algorithm to count the
number of significant inversions between two orderings.
解题思路:
根据本题的叙述,我们可以按照一般求逆序数的思路来解决这个问题。除了在计算逆序数加一的时候加入a[i]>3a[j]进行判断即可。根据定义,
我们这样定义一个序列的逆序数:序列a[1],a[2],a[3],a[4],...,a[n]。这个序列的逆序数C,等于a[1],a[2],a[3],a[4],...的逆序数的和。
即C=sum(Ci),其中我们定义Ci为满足a[i]>3*a[j](i<j)的数的总的个数,即Ci=sum(a[i]>3*a[j]),(i<j)。
下面,我们采用递归分治的算法进行伪代码说明解释:
INVERSION(a_array,start_position,end_position)
{
n=a_array.length;
If n==1
return 0;
else
{
mid_position=(start_position+end_position)/2;
N1=INVERSION(a_array,start_position,mid_position);
N2=INVERSION(a_array,mid_position+1,end_position);
N3=Merger(a_array,start_position,end_position);
}
return N=N1+N2+N3;
}
Merge (a_array,start_position,end_position)
{
得到数组a_array分开后的左右数组L_array,R_array;
i=0;j=0;
InversionCount=0;
for(k=0 to end)
{
if (L_array[i]>R_array[j])
{
A[k]=L_array[i];
i++;
}
if(L_array[i]>3*R_array[j])
InversionCount=InversionCount+j-k;
else
{
A[k]=R[j];
j++;
}
}
}
时间复杂性分析:
因为在这里,T(n)<2T(n/2)+cn,其中Merge的时间复杂度为cn,每一次的递归,规模减半,因此最终的时间复杂度为o(n log n).