Source code for tryalgo.left_right_inversions
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""\
Left and right inversions in a table
christoph dürr - 2016-2019
"""
# snip{
# pylint: disable=too-many-arguments, missing-docstring
def _merge_sort(tab, tmp, rank, left, right, lo, hi):
if hi <= lo + 1: # interval is empty or singleton
return # nothing to do
mid = lo + (hi - lo) // 2 # divide interval into [lo:mid], [mid:hi]
_merge_sort(tab, tmp, rank, left, right, lo, mid)
_merge_sort(tab, tmp, rank, left, right, mid, hi)
i = lo # merge both lists
j = mid
k = lo
while k < hi:
if i < mid and (j == hi or tab[rank[i]] <= tab[rank[j]]):
tmp[k] = rank[i]
right[rank[i]] += j - mid
i += 1
else:
tmp[k] = rank[j]
left[rank[j]] += mid - i
j += 1
k += 1
for k in range(lo, hi): # copy sorted segment into original table
rank[k] = tmp[k]
# pylint: disable=anomalous-backslash-in-string
[docs]
def left_right_inversions(tab):
""" Compute left and right inversions of each element of a table.
:param tab: list with comparable elements
:returns: lists left and right. left[j] = the number of
i<j such that tab[i] > tab[j].
right[i] = the number of i<j such that tab[i] > tab[j].
:complexity: `O(n log n)`
"""
n = len(tab)
left = [0] * n
right = [0] * n
tmp = [None] * n # temporary table
rank = list(range(n))
_merge_sort(tab, tmp, rank, left, right, 0, n)
return left, right
# snip}