int数组的最优反演计数

时间:2011-05-16 23:33:22

标签: algorithm sorting language-agnostic

今天我正在寻找当地信息学奥林匹克运动会的最新考试,我发现了一个有趣的问题。简而言之,它要求给定一个整数数组,计算它有多少个反转,其中反转是一对标记iji > jA[i] < A[j] 。非正式地,反转的数量是无序的对的数量。最初我做了一个O(n²)解决方案(是的,天真的解决方案),但是看到它不适合输入的大小,我想到了更多的问题然后我意识到它可以做到这一点在O(n log n)时间内,通过合并排序的变体来处理输入的大小。

但是看到输入约束(n之间的1 and M整数,并且没有重复),我想知道我的解决方案是否是最优的,或者你知道是否有任何其他解决方案来解决这个问题节拍O(n log n)运行时?

3 个答案:

答案 0 :(得分:5)

由于Chan and Patrascu,文献中的最佳结果是O(n√(log n))算法。不知道常数。

答案 1 :(得分:1)

据我所知,

O(n log n)是最好的。

这里给出了详细的解释:

http://www.geeksforgeeks.org/counting-inversions/

答案 2 :(得分:0)

如果我们假设用于表示整数的位数是常数(比如32或64位),则可以在O(N)时间内解决。

这是一个示例python实现。

http://ideone.com/g57O87


def inv_count(a, m=(1<<32)):
  if not m or not a:
      return 0
  count = 0
  ones = []
  zeros = []
  for n in a:
    if n & m:
      ones.append(n & ~m)
    else:
      count += len(ones)
      zeros.append(n & ~m)
  m /= 2
  return count + inv_count(ones, m) + inv_count(zeros, m)

print inv_count([1, 2, 3, 4, 5]) print inv_count([5, 4, 3, 2, 1])

我们能够实现低于O(N x Log(N))的时间复杂度,因为我们使用非比较排序算法背后的思想,即基数排序,以获得计数。