今天我正在寻找当地信息学奥林匹克运动会的最新考试,我发现了一个有趣的问题。简而言之,它要求给定一个整数数组,计算它有多少个反转,其中反转是一对标记i
,j
,i > j
和A[i] < A[j]
。非正式地,反转的数量是无序的对的数量。最初我做了一个O(n²)
解决方案(是的,天真的解决方案),但是看到它不适合输入的大小,我想到了更多的问题然后我意识到它可以做到这一点在O(n log n)
时间内,通过合并排序的变体来处理输入的大小。
但是看到输入约束(n
之间的1 and M
整数,并且没有重复),我想知道我的解决方案是否是最优的,或者你知道是否有任何其他解决方案来解决这个问题节拍O(n log n)
运行时?
答案 0 :(得分:5)
由于Chan and Patrascu,文献中的最佳结果是O(n√(log n))算法。不知道常数。
答案 1 :(得分:1)
答案 2 :(得分:0)
如果我们假设用于表示整数的位数是常数(比如32或64位),则可以在O(N)时间内解决。
这是一个示例python实现。
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))的时间复杂度,因为我们使用非比较排序算法背后的思想,即基数排序,以获得计数。