数组的反转计数表示 - 数组的排序距离(或接近)。如果数组已经排序,则反转计数为0.如果数组按相反顺序排序,则反转计数最大。 从形式上讲,如果a [i]> 1,则[i]和[j]两个元素形成反转。 a [j]和i< j示例: 序列2,4,1,3,5有三个反转(2,1),(4,1),(4,3)。
现在,有各种算法可以在O(n log n)中解决这个问题。
有一种特殊情况,数组只有3种类型的元素--1,2和3.现在,是否可以计算O(n)中的反转?
例如1,1,3,2,3,1,3
答案 0 :(得分:4)
是的。只需取3个整数a,b,c
,其中a
是1到1的遇到的数量,b
是迄今为止遇到的2个数,c
是到目前为止遇到的3个人数。鉴于此,遵循下面的算法(我假设数字在数组arr
中给出,大小为n
,基于1的索引,也只是一个伪代码)
no_of_inv = 0
a = 0
b = 0
c = 0
for i from 1 to n:
if arr[i] == 1:
no_of_inv = no_of_inv + b + c
a++
else if arr[i] == 2:
no_of_inv = no_of_inv + c
b++
else:
c++
答案 1 :(得分:1)
(这个算法与Sasha非常相似。我只是想提供一个解释。)
每次反转(i, j)
都满足0 ≤ i < j < n
。我们将S[j]
定义为(i, j)
形式的反转次数;也就是说,S[j]
是A[i] > A[j]
的{{1}}次。然后,反转的总数为0 ≤ i < j
。
让T = S[0] + S[1] + … + S[n - 1]
为C[x][j]
的{{1}}次。所有A[i] > x
然后0 ≤ i < j
。如果我们可以在线性时间内计算S[j] = C[A[j]][j]
值j
,那么我们可以在线性时间内计算3n
。
这是一些Python代码:
C[x][j]
通过不同时存储所有S
值,可以提高效率 - 尽管不是在asmpytotic术语中。该算法实际上只需要通过数组一次。我选择以这种方式呈现它,因为它最简洁。