From 82a8273cb243cec44a5784c0f0207a06dc2598b6 Mon Sep 17 00:00:00 2001 From: coderbeta1 Date: Fri, 6 Oct 2023 00:36:05 +0530 Subject: [PATCH 1/4] Added Median of Medians Algorithm --- searches/median_of_medians.py | 115 ++++++++++++++++++++++++++++++++++ 1 file changed, 115 insertions(+) create mode 100644 searches/median_of_medians.py diff --git a/searches/median_of_medians.py b/searches/median_of_medians.py new file mode 100644 index 000000000000..41dcfc72e374 --- /dev/null +++ b/searches/median_of_medians.py @@ -0,0 +1,115 @@ +""" +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 +""" + +""" +>>> 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 +""" + +def median_of_five(arr: list) -> int: + """ + >>> 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]) + 3 + >>> median_of_five([3, 5, 7, 10, 2]) + 5 + """ + """ + Return the median of the input list + :param arr: Array to find median of + :return: median of arr + """ + arr=sorted(arr) + return arr[len(arr) // 2] + +def median_of_medians(arr: list) -> int: + """ + >>> 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 + """ + """ + 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 + """ + 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: + """ + >>> 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 + """ + + """ + 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 + """ + + # 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 From 68a3fdb7ace5abd6b374b50ac6d616a36dfb9c84 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 5 Oct 2023 19:09:55 +0000 Subject: [PATCH 2/4] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- searches/median_of_medians.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/searches/median_of_medians.py b/searches/median_of_medians.py index 41dcfc72e374..ba8c4d7cd94d 100644 --- a/searches/median_of_medians.py +++ b/searches/median_of_medians.py @@ -19,6 +19,7 @@ 5 """ + def median_of_five(arr: list) -> int: """ >>> median_of_five([2, 4, 5, 7, 899]) @@ -35,9 +36,10 @@ def median_of_five(arr: list) -> int: :param arr: Array to find median of :return: median of arr """ - arr=sorted(arr) + arr = sorted(arr) return arr[len(arr) // 2] + def median_of_medians(arr: list) -> int: """ >>> median_of_medians([2, 4, 5, 7, 899, 54, 32]) @@ -67,6 +69,7 @@ def median_of_medians(arr: list) -> int: i += 5 return median_of_medians(medians) + def quick_select(arr: list, target: int) -> int: """ >>> quick_select([2, 4, 5, 7, 899, 54, 32], 5) @@ -106,7 +109,7 @@ def quick_select(arr: list, target: int) -> int: else: right.append(arr[i]) rank_x = len(left) + 1 - if(rank_x == target): + if rank_x == target: answer = x elif rank_x > target: answer = quick_select(left, target) From c767c6641d09811c44d620c33bddf1eaf907c071 Mon Sep 17 00:00:00 2001 From: Achal Jain Date: Fri, 6 Oct 2023 08:19:55 +0530 Subject: [PATCH 3/4] Update median_of_medians.py as per requested changes --- searches/median_of_medians.py | 57 +++++++++++++---------------------- 1 file changed, 21 insertions(+), 36 deletions(-) diff --git a/searches/median_of_medians.py b/searches/median_of_medians.py index ba8c4d7cd94d..a7bc2e020acc 100644 --- a/searches/median_of_medians.py +++ b/searches/median_of_medians.py @@ -8,40 +8,31 @@ https://en.wikipedia.org/wiki/Median_of_medians """ -""" ->>> 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 -""" - - 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]) - 3 + 4 >>> median_of_five([3, 5, 7, 10, 2]) 5 """ - """ - Return the median of the input list - :param arr: Array to find median of - :return: median of arr - """ - arr = sorted(arr) + 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]) @@ -51,12 +42,7 @@ def median_of_medians(arr: list) -> int: >>> median_of_medians([3, 5, 7, 10, 2, 12]) 12 """ - """ - 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 - """ + if len(arr) <= 5: return median_of_five(arr) medians = [] @@ -69,9 +55,14 @@ def median_of_medians(arr: list) -> int: 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) @@ -82,14 +73,6 @@ def quick_select(arr: list, target: int) -> int: 5 """ - """ - 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 - """ - # Invalid Input if target > len(arr): return -1 @@ -109,10 +92,12 @@ def quick_select(arr: list, target: int) -> int: else: right.append(arr[i]) rank_x = len(left) + 1 - if rank_x == target: + 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])) From 328a2df3b3dfe5d29307e2ce9673cf3a52edefa8 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 6 Oct 2023 02:50:42 +0000 Subject: [PATCH 4/4] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- searches/median_of_medians.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/searches/median_of_medians.py b/searches/median_of_medians.py index a7bc2e020acc..a8011a34af76 100644 --- a/searches/median_of_medians.py +++ b/searches/median_of_medians.py @@ -8,6 +8,7 @@ https://en.wikipedia.org/wiki/Median_of_medians """ + def median_of_five(arr: list) -> int: """ Return the median of the input list @@ -23,9 +24,10 @@ def median_of_five(arr: list) -> int: >>> median_of_five([3, 5, 7, 10, 2]) 5 """ - arr=sorted(arr) + arr = sorted(arr) return arr[len(arr) // 2] + def median_of_medians(arr: list) -> int: """ Return a pivot to partition data on by calculating @@ -55,6 +57,7 @@ def median_of_medians(arr: list) -> int: 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, @@ -62,7 +65,7 @@ def quick_select(arr: list, target: int) -> int: :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) @@ -92,7 +95,7 @@ def quick_select(arr: list, target: int) -> int: else: right.append(arr[i]) rank_x = len(left) + 1 - if(rank_x == target): + if rank_x == target: answer = x elif rank_x > target: answer = quick_select(left, target) @@ -100,4 +103,5 @@ def quick_select(arr: list, target: int) -> int: answer = quick_select(right, target - rank_x) return answer + print(median_of_five([5, 4, 3, 2]))