Skip to content

Commit 0317a96

Browse files
Baraff24pre-commit-ci[bot]cclauss
authored
Add the algorithm to search the minimum element of an array using the… (#9688)
* Add the algorithm to search the minimum element of an array using the divide-and-conquer algorithm for selection sort * Update minimum_element_of_array.py Resolved Ruff warning * Update minimum_element_of_array.py Add type hint for every function * Update minimum_element_of_array.py Resolve Ruff error: Error: divide_and_conquer/minimum_element_of_array.py:13:1: I001 Import block is un-sorted or un-formatted * Update minimum_element_of_array.py Resolve Ruff errors * Update minimum_element_of_array.py * Update minimum_element_of_array.py Update name of variables * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update minimum_element_of_array.py Update line lenght * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Fix comments and documentation in minimum_element_of_array.py Corrected minor grammatical errors and improved clarity in comments. * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Refactor selection_sort return type Updated the return type of selection_sort function to simplify it. --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Christian Clauss <cclauss@me.com>
1 parent 322cd42 commit 0317a96

1 file changed

Lines changed: 129 additions & 0 deletions

File tree

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
"""
2+
Return the minimum element of an array using the
3+
divide-and-conquer algorithm for selection sort.
4+
Like quicksort, it partitions the input array recursively.
5+
But unlike quicksort,
6+
which recursively processes both sides of the partition,
7+
this algorithm works on only one side of the partition.
8+
The expected running time of this selection sort algorithm is 0(n),
9+
assuming that the elements are distinct.
10+
It returns the ith smallest element of the array A[p: r], where 1 ≤ i ≤ r-p+1.
11+
(From Introduction to Algorithms, Fourth Edition, Cormen, 2022: Chapter 9.2)
12+
"""
13+
14+
from __future__ import annotations
15+
16+
import random
17+
18+
19+
def partition(array: list, starting_index: int, ending_index: int) -> int:
20+
"""
21+
Partition the array.
22+
Args:
23+
array: list of elements
24+
starting_index: starting index of the array
25+
ending_index: ending index of the array
26+
27+
Returns:
28+
index of the pivot
29+
30+
>>> arr = [-2, 3, -10, 11, 99, 100000, 100, -200]
31+
>>> partition(arr, 0, len(arr) - 1)
32+
0
33+
"""
34+
pivot = array[ending_index]
35+
i = starting_index - 1
36+
for j in range(starting_index, ending_index):
37+
if array[j] <= pivot:
38+
i += 1
39+
array[i], array[j] = array[j], array[i]
40+
array[i + 1], array[ending_index] = array[ending_index], array[i + 1]
41+
return i + 1
42+
43+
44+
def randomized_partition(array: list, starting_index: int, ending_index: int) -> int:
45+
"""
46+
Randomized partition of the array.
47+
Args:
48+
array: list of elements
49+
starting_index: starting index of the array
50+
ending_index: ending index of the array
51+
52+
Returns:
53+
call to partition function
54+
55+
>>> arr = [-2, 3, -10, 11, 99, 100000, 100, -200]
56+
>>> arr1 = randomized_partition(arr, 0, len(arr) - 1)
57+
>>> arr == arr1
58+
False
59+
"""
60+
61+
rand_idx = random.randint(starting_index, ending_index)
62+
array[rand_idx], array[ending_index] = array[ending_index], array[rand_idx]
63+
return partition(array, starting_index, ending_index)
64+
65+
66+
def selection_sort(
67+
array: list, starting_index: int, ending_index: int, smallest_element: int
68+
) -> list | None:
69+
"""
70+
Returns a list of sorted array elements using selection sort.
71+
Using selection to find a minimum is O(n) overkill vs. a linear scan — the
72+
value here is the DAC/partition demonstration.
73+
74+
Args:
75+
array: list of elements
76+
starting_index: starting index of the array
77+
ending_index: ending index of the array
78+
smallest_element: the ith smallest element of
79+
the array A[p: r], where 1 ≤ i ≤ r-p+1
80+
81+
Returns:
82+
sorted array
83+
84+
>>> from random import shuffle
85+
>>> arr = [-2, 3, -10, 11, 99, 100000, 100, -200]
86+
>>> shuffle(arr)
87+
>>> selection_sort(arr, 0, len(arr) - 1, 1)
88+
-200
89+
90+
>>> shuffle(arr)
91+
>>> selection_sort(arr, 0, len(arr) - 1, 1)
92+
-200
93+
94+
>>> arr = [-200]
95+
>>> selection_sort(arr, 0, len(arr) - 1, 1)
96+
-200
97+
98+
>>> arr = [-2]
99+
>>> selection_sort(arr, 0, len(arr) - 1, 1)
100+
-2
101+
102+
>>> arr = []
103+
>>> selection_sort(arr, 0, len(arr) - 1, 1)
104+
[]
105+
"""
106+
107+
if not array:
108+
return array
109+
110+
if starting_index == ending_index:
111+
# 1 <= i <= r - p + 1 when p == r means that i == 1
112+
return array[starting_index]
113+
114+
q = randomized_partition(array, starting_index, ending_index)
115+
116+
k = q - starting_index + 1
117+
118+
if smallest_element == k:
119+
return array[q] # the pivot value is the answer
120+
if smallest_element < k:
121+
return selection_sort(array, starting_index, q - 1, smallest_element)
122+
else:
123+
return selection_sort(array, q + 1, ending_index, smallest_element - k)
124+
125+
126+
if __name__ == "__main__":
127+
import doctest
128+
129+
doctest.testmod()

0 commit comments

Comments
 (0)