mirror of
https://github.com/TheAlgorithms/Python.git
synced 2024-11-23 21:11:08 +00:00
Added Median of Medians Algorithm (#9864)
* Added Median of Medians Algorithm * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update median_of_medians.py as per requested changes * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
This commit is contained in:
parent
c8f6f79f80
commit
17de908d1a
107
searches/median_of_medians.py
Normal file
107
searches/median_of_medians.py
Normal file
|
@ -0,0 +1,107 @@
|
|||
"""
|
||||
A Python implementation of the Median of Medians algorithm
|
||||
to select pivots for quick_select, which is efficient for
|
||||
calculating the value that would appear in the index of a
|
||||
list if it would be sorted, even if it is not already
|
||||
sorted. Search in time complexity O(n) at any rank
|
||||
deterministically
|
||||
https://en.wikipedia.org/wiki/Median_of_medians
|
||||
"""
|
||||
|
||||
|
||||
def median_of_five(arr: list) -> int:
|
||||
"""
|
||||
Return the median of the input list
|
||||
:param arr: Array to find median of
|
||||
:return: median of arr
|
||||
|
||||
>>> median_of_five([2, 4, 5, 7, 899])
|
||||
5
|
||||
>>> median_of_five([5, 7, 899, 54, 32])
|
||||
32
|
||||
>>> median_of_five([5, 4, 3, 2])
|
||||
4
|
||||
>>> median_of_five([3, 5, 7, 10, 2])
|
||||
5
|
||||
"""
|
||||
arr = sorted(arr)
|
||||
return arr[len(arr) // 2]
|
||||
|
||||
|
||||
def median_of_medians(arr: list) -> int:
|
||||
"""
|
||||
Return a pivot to partition data on by calculating
|
||||
Median of medians of input data
|
||||
:param arr: The data to be checked (a list)
|
||||
:return: median of medians of input array
|
||||
|
||||
>>> median_of_medians([2, 4, 5, 7, 899, 54, 32])
|
||||
54
|
||||
>>> median_of_medians([5, 7, 899, 54, 32])
|
||||
32
|
||||
>>> median_of_medians([5, 4, 3, 2])
|
||||
4
|
||||
>>> median_of_medians([3, 5, 7, 10, 2, 12])
|
||||
12
|
||||
"""
|
||||
|
||||
if len(arr) <= 5:
|
||||
return median_of_five(arr)
|
||||
medians = []
|
||||
i = 0
|
||||
while i < len(arr):
|
||||
if (i + 4) <= len(arr):
|
||||
medians.append(median_of_five(arr[i:].copy()))
|
||||
else:
|
||||
medians.append(median_of_five(arr[i : i + 5].copy()))
|
||||
i += 5
|
||||
return median_of_medians(medians)
|
||||
|
||||
|
||||
def quick_select(arr: list, target: int) -> int:
|
||||
"""
|
||||
Two way partition the data into smaller and greater lists,
|
||||
in relationship to the pivot
|
||||
:param arr: The data to be searched (a list)
|
||||
:param target: The rank to be searched
|
||||
:return: element at rank target
|
||||
|
||||
>>> quick_select([2, 4, 5, 7, 899, 54, 32], 5)
|
||||
32
|
||||
>>> quick_select([2, 4, 5, 7, 899, 54, 32], 1)
|
||||
2
|
||||
>>> quick_select([5, 4, 3, 2], 2)
|
||||
3
|
||||
>>> quick_select([3, 5, 7, 10, 2, 12], 3)
|
||||
5
|
||||
"""
|
||||
|
||||
# Invalid Input
|
||||
if target > len(arr):
|
||||
return -1
|
||||
|
||||
# x is the estimated pivot by median of medians algorithm
|
||||
x = median_of_medians(arr)
|
||||
left = []
|
||||
right = []
|
||||
check = False
|
||||
for i in range(len(arr)):
|
||||
if arr[i] < x:
|
||||
left.append(arr[i])
|
||||
elif arr[i] > x:
|
||||
right.append(arr[i])
|
||||
elif arr[i] == x and not check:
|
||||
check = True
|
||||
else:
|
||||
right.append(arr[i])
|
||||
rank_x = len(left) + 1
|
||||
if rank_x == target:
|
||||
answer = x
|
||||
elif rank_x > target:
|
||||
answer = quick_select(left, target)
|
||||
elif rank_x < target:
|
||||
answer = quick_select(right, target - rank_x)
|
||||
return answer
|
||||
|
||||
|
||||
print(median_of_five([5, 4, 3, 2]))
|
Loading…
Reference in New Issue
Block a user