mirror of
https://github.com/TheAlgorithms/Python.git
synced 2026-09-28 21:45:27 +08:00
* 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>
130 lines
3.7 KiB
Python
130 lines
3.7 KiB
Python
"""
|
|
Return the minimum element of an array using the
|
|
divide-and-conquer algorithm for selection sort.
|
|
Like quicksort, it partitions the input array recursively.
|
|
But unlike quicksort,
|
|
which recursively processes both sides of the partition,
|
|
this algorithm works on only one side of the partition.
|
|
The expected running time of this selection sort algorithm is 0(n),
|
|
assuming that the elements are distinct.
|
|
It returns the ith smallest element of the array A[p: r], where 1 ≤ i ≤ r-p+1.
|
|
(From Introduction to Algorithms, Fourth Edition, Cormen, 2022: Chapter 9.2)
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import random
|
|
|
|
|
|
def partition(array: list, starting_index: int, ending_index: int) -> int:
|
|
"""
|
|
Partition the array.
|
|
Args:
|
|
array: list of elements
|
|
starting_index: starting index of the array
|
|
ending_index: ending index of the array
|
|
|
|
Returns:
|
|
index of the pivot
|
|
|
|
>>> arr = [-2, 3, -10, 11, 99, 100000, 100, -200]
|
|
>>> partition(arr, 0, len(arr) - 1)
|
|
0
|
|
"""
|
|
pivot = array[ending_index]
|
|
i = starting_index - 1
|
|
for j in range(starting_index, ending_index):
|
|
if array[j] <= pivot:
|
|
i += 1
|
|
array[i], array[j] = array[j], array[i]
|
|
array[i + 1], array[ending_index] = array[ending_index], array[i + 1]
|
|
return i + 1
|
|
|
|
|
|
def randomized_partition(array: list, starting_index: int, ending_index: int) -> int:
|
|
"""
|
|
Randomized partition of the array.
|
|
Args:
|
|
array: list of elements
|
|
starting_index: starting index of the array
|
|
ending_index: ending index of the array
|
|
|
|
Returns:
|
|
call to partition function
|
|
|
|
>>> arr = [-2, 3, -10, 11, 99, 100000, 100, -200]
|
|
>>> arr1 = randomized_partition(arr, 0, len(arr) - 1)
|
|
>>> arr == arr1
|
|
False
|
|
"""
|
|
|
|
rand_idx = random.randint(starting_index, ending_index)
|
|
array[rand_idx], array[ending_index] = array[ending_index], array[rand_idx]
|
|
return partition(array, starting_index, ending_index)
|
|
|
|
|
|
def selection_sort(
|
|
array: list, starting_index: int, ending_index: int, smallest_element: int
|
|
) -> list | None:
|
|
"""
|
|
Returns a list of sorted array elements using selection sort.
|
|
Using selection to find a minimum is O(n) overkill vs. a linear scan — the
|
|
value here is the DAC/partition demonstration.
|
|
|
|
Args:
|
|
array: list of elements
|
|
starting_index: starting index of the array
|
|
ending_index: ending index of the array
|
|
smallest_element: the ith smallest element of
|
|
the array A[p: r], where 1 ≤ i ≤ r-p+1
|
|
|
|
Returns:
|
|
sorted array
|
|
|
|
>>> from random import shuffle
|
|
>>> arr = [-2, 3, -10, 11, 99, 100000, 100, -200]
|
|
>>> shuffle(arr)
|
|
>>> selection_sort(arr, 0, len(arr) - 1, 1)
|
|
-200
|
|
|
|
>>> shuffle(arr)
|
|
>>> selection_sort(arr, 0, len(arr) - 1, 1)
|
|
-200
|
|
|
|
>>> arr = [-200]
|
|
>>> selection_sort(arr, 0, len(arr) - 1, 1)
|
|
-200
|
|
|
|
>>> arr = [-2]
|
|
>>> selection_sort(arr, 0, len(arr) - 1, 1)
|
|
-2
|
|
|
|
>>> arr = []
|
|
>>> selection_sort(arr, 0, len(arr) - 1, 1)
|
|
[]
|
|
"""
|
|
|
|
if not array:
|
|
return array
|
|
|
|
if starting_index == ending_index:
|
|
# 1 <= i <= r - p + 1 when p == r means that i == 1
|
|
return array[starting_index]
|
|
|
|
q = randomized_partition(array, starting_index, ending_index)
|
|
|
|
k = q - starting_index + 1
|
|
|
|
if smallest_element == k:
|
|
return array[q] # the pivot value is the answer
|
|
if smallest_element < k:
|
|
return selection_sort(array, starting_index, q - 1, smallest_element)
|
|
else:
|
|
return selection_sort(array, q + 1, ending_index, smallest_element - k)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
import doctest
|
|
|
|
doctest.testmod()
|