Reputation: 936
Today I was looking the latest exam of the local informatics olympiad and I found a interesting problem. Briefly, it asks to, given an integer array, count how many inversions it has, where an inversion is a pair of indicies i
, j
such that i > j
and A[i] < A[j]
. Informally, the number of inversions is the number of pairs that are out of order. Initially I made a O(n²)
solution (yes, the naive one), but seeing it wouldn't fit well with the size of the input, I thought about the problem a bit more and then I realized it's possible to do it within O(n log n)
time by a variant of merge sort, which handles good the size of the input.
But seeing the input constraints (n
integers between 1 and M
, and no duplicates), I was wondering if my solution is optimal, or do you know if is there any other solution to this problem that beats O(n log n)
runtime?
Upvotes: 8
Views: 1044
Reputation: 1684
If we assume the number of bits used to represent the integer is constant (say 32 or 64 bits), this can be solved in O(N) time.
Here is an example python implementation.
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])
We are able to achieve less than O(N x Log(N)) time complexity, as we are using idea behind a non-comparative sorting algorithm, radix sort, to get the count.
Upvotes: 0
Reputation: 2321
O(n log n) is the best as far as I know.
A detailed explanation was given here:
http://www.geeksforgeeks.org/counting-inversions/
Upvotes: 1
Reputation: 121
The best result in the literature is an O(n √(log n)) algorithm due to Chan and Patrascu. No idea about the constant.
Upvotes: 5