在(x,y)
形式的2维平面上给出一组n个点,目的是找到所有点(xi,yi)
和(xj, yj)
的对数,使得连接两点的线有一个负斜率。
假设没有两个xi
具有相同的值。假设所有点都在[-100,100]
或其他范围内。
答案 0 :(得分:8)
您所询问的内容相当于在y
对点进行排序时,您将获得x
数组中的非反转次数。你可以负担这种排序 - 它是O(n log n)
。
我提醒您,反转是i
> j
和a[i]
< a[j]
。我所说的等价很容易证明。
想象一下,你有6分(4,4),(2,1),(6,6),(3,3),(5,2),(1,5)。在对x
进行排序后,您获得:(1,5),(2,1),(3,3),(4,4),(5,2),(6,6) 。您可以看到负斜率由<(2,1),(3,3)>,<(2,1),(4,4)>,<(2,1), (5,2)>,<(2,1),(6,6)>等y
s不反转的所有对。
使用合并排序算法的扩充可以在O(n log n)
中计算反转次数:基本上,每次选择添加右子阵列的值时,您只需要增加反转计数器(包含较大索引的值) )。您可以使用左子阵列中尚未处理的值来增加反转次数。
以下是计算反转次数的示例。
Initial array 5 1 3 4 2 6 inv := 0 // Total inversions: 6
merge step 1: <5 1 3> <4 2 6> inv = 0
merge step 2: <5> <1 3> | <4> <2 6> inv = 0
merge step 3: <5> [<1> <3>] | <4> [<2> <6>] inv = 0
merge step 4: <5> <1 3> | <4> <2 6> inv = 0 // both pairs were already sorted
merge step 5: <1 3 5> | <2 4 6> inv = 3 // we add one for 1, 3 and 2
merge step 6 <1 2 3 4 5 6> inv = 6 // we add 2 (3 and 5) for 2 and 1 for 4
在您找到反转次数后,总对数(n * (n - 1)) / 2
中的非反转次数减去反转次数inv
。
在示例中,这是:6 * 5 / 2 - 6 = 9
。