设A是一个大小为N
的数组。
如果(i,j)
和i < j
A[i] > A[j]
称为“反向”
我需要找到一个接收大小为N
的数组(带有唯一数字)的算法,并返回O(n*log(n))
时间内的倒数。
答案 0 :(得分:25)
您可以使用merge sort算法。
在合并算法的循环中,左半部分和右半部分都是按升序排序的,我们希望将它们合并为一个排序的数组。请注意,右侧的所有元素都具有比左侧更高的索引。
假设 array [leftIndex]&gt;阵列[rightIndex] 即可。这意味着索引 leftIndex 元素后左侧部分中的所有元素也大于右侧当前元素(因为左侧按升序排序)。因此,右侧的当前元素会生成 numberOfElementsInTheLeftSide - leftIndex + 1 反转,因此请将其添加到全局反转计数中。
一旦算法完成执行,你得到答案,并且在最坏的情况下合并排序是 O(n log n)。
答案 1 :(得分:12)
Cham和Patrascu于2010年在SIAM上发表了一篇名为Counting Inversions, Offline Orthogonal Range Counting, and Related Problems的文章,该文章给出了一个采用O(n sqrt(log(n)))时间的算法。这是目前最着名的算法,并且改进了长期存在的O(n log(n)/ log(log(n)))算法。从摘要:
我们提供 O(n sqrt(lg n)) -time算法 用于计算反转次数 在n个元素的排列中。这个 改善了以前的长期存在 O(n lg n / lg lg n)的界限 接着来自Dietz的数据结构 [WADS'89],并回答了一个问题 安德森和彼得森[SODA'95]。如 Dietz的结果被认为是最佳的 对于相关的动态排名问题, 我们的结果显示了重大意义 离线设置的改进。
我们的新技术非常简单:我们 执行a的“垂直分区” 特里(类似于范埃姆德博阿斯树), 并使用来自外部记忆的想法。 然而,该技术发现了许多 应用程序:例如,我们获取
- 在 d 维度中,算法为 回答 n 离线正交范围 及时计算查询 O(n lg d-2 + 1 / d n);
- 一个改进 在线数据的建设时间 正交范围的结构 数数;
- 改进了更新时间 对于部分和的问题;
- 更快 用于查找的Word RAM算法 安排的最大深度 轴对齐的矩形,并用于 坡度选择问题。
作为奖励, 我们也给出一个简单的 (1 +ε) - 近似算法 计算运行中的反转 线性时间,改善以前 O(n lg lg n)受Andersson和 皮特森。
答案 2 :(得分:10)
我认为最好的方法(这只是因为我喜欢数据结构)是使用binary indexed tree。请注意,如果你需要的只是一个解决方案,合并排序也会起作用(我只是认为这个概念完全是摇滚!)。基本思想是这样的:构建一个更新O(log n)中的值的数据结构,并回答查询“到目前为止,数组中已经发生了多少小于x的数字?”鉴于此,您可以轻松回答有多少大于x,这有助于反转,x作为对中的第二个数字。例如,考虑列表{3,4,1,2}。
当处理3时,到目前为止没有其他数字,因此右侧3的反转= 0 当处理4时,到目前为止小于4的数字= 1,因此数字越多(因此倒数)= 0 现在,当处理1,小于1 = 0的数字时,这个更大的数字= 2,这有助于两个反转(3,1)和(4,1)。同样的逻辑适用于2,它找到比它小1的数字,因此比它大2。
现在,唯一的问题是要了解这些更新和查询如何在log n中发生。上面提到的url是我读过的关于这个主题的最好的教程之一。
答案 3 :(得分:0)
这些是原始的MERGE和MERGE-SORT算法 来自Cormen,Leiserson,Rivest,Stein算法简介:
MERGE(A,p,q,r)
1 n1 = q - p + 1
2 n2 = r - q
3 let L[1..n1 + 1] and R[1..n2 + 1] be new arrays
4 for i = 1 to n1
5 L[i] = A[p + i - 1]
6 for j = 1 to n2
7 R[j] = A[q + j]
8 L[n1 + 1] = infinity
9 R[n2 + 1] = infinity
10 i = 1
11 j = 1
12 for k = p to r
13 if L[i] <= R[j]
14 A[k] = L[i]
15 i = i + 1
16 else A[k] = R[j]
17 j = j + 1
和
MERGE-SORT(A,p,r)
1 if p < r
2 q = floor((p + r)/2)
3 MERGE-SORT(A,p,q)
4 MERGE-SORT(A,q + 1,r)
5 MERGE(A,p,q,r)
在MERGE infinity的第8和第9行是所谓的前哨卡,
它具有所有数组元素都小于它的值。
要获得反转次数,可以引入全局计数器,
让我们说ninv在调用MERGE-SORT之前初始化为零
而不是通过添加一行来修改MERGE算法
在第16行之后的else语句中,类似
ninv += n1 - i
比MERGE-SORT完成后,ninv将保持反转次数