Finding the number of inversions

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(nlogn) algorithm to count the number of significant inversions between two orderings.

类似于求逆序数的个数,不断地将序列A分割为2个子序列,在递归调用时计算各一半的逆序数,在进行合并时再分别计算位于左边和右边的逆序数。递归对序列进行分割时,序列中剩一个数时就无法再分了。在合并的函数中,比较左边L[i]和右边子数组的R[j],如果L[i] > 3R[j],那么L[i]后面的数都比 3R[j]要大,不需要再比较了,因此逆序数的个数增加了子数组L的长度减i个。

当在单个子数组内求逆序对的个数时,显然是没有问题的。

当在两个子数组之间合并并求逆序对的个数时,假设两个子数组分别为A[]和B[],则两个数组的长度分别为Length(A)和Length(B),并且这两个子数组都已经是有序的(从小大排列),当A[i] > B[j]时,数组A[i]至A[Length(a)]这些值都是大于B[j]的。

MergeAndCount()函数中,需要循环执行的是两个for循环,因此该函数的时间复杂度为O(n)。根据二分算法,序列A最多能被分割log 2 n次,也就是MergeAndCount()函数最多可以执行 log 2 n次。因此时间复杂度为O(nlog 2 n)。

伪代码如下:


这里写图片描述

猜你喜欢

转载自blog.csdn.net/violet_echo_0908/article/details/78923276