The Wayback Machine - https://web.archive.org/web/20211017081317/https://github.com/TheAlgorithms/Python/pull/4824/files
Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Algorithm Optimized #4824

Merged
merged 6 commits into from Oct 11, 2021
@@ -2,31 +2,25 @@
Given an array-like data structure A[1..n], how many pairs
(i, j) for all 1 <= i < j <= n such that A[i] > A[j]? These pairs are
called inversions. Counting the number of such inversions in an array-like
object is the important. Among other things, counting inversions can help
us determine how close a given array is to being sorted
object is the important. Among other things, counting inversions can help
us determine how close a given array is to being sorted.
In this implementation, I provide two algorithms, a divide-and-conquer
algorithm which runs in nlogn and the brute-force n^2 algorithm.
"""


def count_inversions_bf(arr):
"""
Counts the number of inversions using a a naive brute-force algorithm
Parameters
----------
arr: arr: array-like, the list containing the items for which the number
of inversions is desired. The elements of `arr` must be comparable.
Returns
-------
num_inversions: The total number of inversions in `arr`
Examples
---------
>>> count_inversions_bf([1, 4, 2, 4, 1])
This conversation was marked as resolved by mhammadsaani

This comment has been minimized.

@poyea

poyea Oct 6, 2021
Member

we can keep these actually

4
>>> count_inversions_bf([1, 1, 2, 4, 4])
@@ -49,20 +43,16 @@ def count_inversions_bf(arr):
def count_inversions_recursive(arr):
"""
Counts the number of inversions using a divide-and-conquer algorithm
Parameters
-----------
arr: array-like, the list containing the items for which the number
of inversions is desired. The elements of `arr` must be comparable.
Returns
-------
C: a sorted copy of `arr`.
num_inversions: int, the total number of inversions in 'arr'
Examples
--------
>>> count_inversions_recursive([1, 4, 2, 4, 1])
([1, 1, 2, 4, 4], 4)
>>> count_inversions_recursive([1, 1, 2, 4, 4])
@@ -72,40 +62,34 @@ def count_inversions_recursive(arr):
"""
if len(arr) <= 1:
return arr, 0
else:
mid = len(arr) // 2
P = arr[0:mid]
Q = arr[mid:]
mid = len(arr) // 2
P = arr[0:mid]
Q = arr[mid:]

A, inversion_p = count_inversions_recursive(P)
B, inversions_q = count_inversions_recursive(Q)
C, cross_inversions = _count_cross_inversions(A, B)
A, inversion_p = count_inversions_recursive(P)
B, inversions_q = count_inversions_recursive(Q)
C, cross_inversions = _count_cross_inversions(A, B)

num_inversions = inversion_p + inversions_q + cross_inversions
return C, num_inversions
num_inversions = inversion_p + inversions_q + cross_inversions
return C, num_inversions


def _count_cross_inversions(P, Q):
"""
Counts the inversions across two sorted arrays.
And combine the two arrays into one sorted array
For all 1<= i<=len(P) and for all 1 <= j <= len(Q),
if P[i] > Q[j], then (i, j) is a cross inversion
Parameters
----------
P: array-like, sorted in non-decreasing order
Q: array-like, sorted in non-decreasing order
Returns
------
R: array-like, a sorted array of the elements of `P` and `Q`
num_inversion: int, the number of inversions across `P` and `Q`
Examples
--------
>>> _count_cross_inversions([1, 2, 3], [0, 2, 5])
([0, 1, 2, 2, 3, 5], 4)
>>> _count_cross_inversions([1, 2, 3], [3, 4, 5])