Merge sort - inversions count
In an array, arr = [a0, a1, …, aN-1] , the elements at indices i and j (where i < j) form an inversion if aI > aJ. In other words, inverted elements and are considered to be “out of order”. To correct an inversion, we can swap adjacent elements.
For example, consider arr = [2,4,1]. It has two inversions: (4,1) and (2,1). To sort the array, we must perform the following two swaps to correct the inversions: [2,4,1] -> [2,1,4] -> [1,2,4].
Wikipedia article about merge sort algorithm.
Python implementation
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | def count_inversions(lst): return merge_count_inversion(lst)[1] def merge_count_inversion(lst): if len(lst) <= 1: return lst, 0 middle = int( len(lst) / 2 ) left, a = merge_count_inversion(lst[:middle]) right, b = merge_count_inversion(lst[middle:]) result, c = merge_count_split_inversion(left, right) return result, (a + b + c) def merge_count_split_inversion(left, right): result = [] count = 0 i, j = 0, 0 left_len = len(left) while i < left_len and j < len(right): if left[i] <= right[j]: result.append(left[i]) i += 1 else: result.append(right[j]) count += left_len - i j += 1 result += left[i:] result += right[j:] return result, count |
Erlang Implementation
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | inv_count(L) when length(L) =< 1 -> {0, L}; inv_count(L) -> {L1, L2} = lists:split(length(L) div 2, L), {A, Left} = inv_count(L1), {B, Right} = inv_count(L2), {C, Res} = mcsi(Left, Right), {A+B+C, Res}. mcsi(L, R) -> mcsi_i(length(L),0,[],L,R). mcsi_i(_, C, Res, [], Right) -> {C, Res ++ Right}; mcsi_i(_, C, Res, Left, []) -> {C, Res ++ Left}; mcsi_i(N, C, Res, [HL|TL] = Left, [HR|TR] = Right) -> case HL =< HR of true -> mcsi_i(N-1, C, Res ++ [HL], TL, Right); false -> mcsi_i(N, C+N, Res ++ [HR], Left, TR) end. |