Przejdź do głównej zawartości

Element najmniejszy/największy listy

W Pythonie możemy skorzystać z funkcji min() lub max(), żeby znaleźć odpowiednio najmniejszy lub największy element danej listy, na przykład w ten sposób:

lista: list[int] = [1, 17, 4, 19, 2, 1, 99, 82, 46]

minimum: int = min(lista)
maximum: int = max(lista)

Warto jednak wiedzieć, jak wygląda standardowy algorytm znajdywania elementu największego/najmniejszego w liście, bez użycia funkcji, ponieważ korzysta on z metody programowania dynamicznego.

Algorytm dynamiczny

Gdybyśmy mieli sami znaleźć najmniejszy element na liście, która ma bardzo dużo elementów (np. lista tak długa, że po wydrukowaniu zajmuje kilka stron A4), to pewnie przeglądalibyśmy po kolei elementy i pamiętalibyśmy w głowie, jaka była najmniejsza wartość, jaką widzieliśmy do tej pory. Dokładnie tak samo możemy zrobić w programowaniu i nazywamy to programowaniem dynamicznym, ponieważ pamiętamy dynamiczną wartość, która jest najlepszym do tej pory znalezionym wynikiem.

Zobaczmy poniższy algorytm:

lista: list[int] = [1, 17, 4, 19, 2, 1, 99, 82, 46]

def min_dyn(l: list[int]) -> int:
res: int = None

for el in l:
if res == None or el < res:
res = el

return res

Na początku tworzymy sobie zmienną res, która będzie naszą pamięcią przechowującą najlepszy znaleziony wynik. Potem w pętli iterujemy się po kolei po wszystkich elementach listy i za każdym razem porównujemy element do aktualnie najlepszego wyniku.

Alternatywnie, moglibyśmy w tym algorytmie zamiast początkowej wartości wyniku None zastosować:

  • -1, jeśli szukamy elementu największego w liście, w której znajdują się tylko liczby nieujemne,
  • l[0], czyli pierwszego elementu listy, jeśli wcześniej sprawdzimy, że nie jest pusta.

Algorytm rekurencyjny

Ciekawym algorytmem pozwalającym na znalezienie elementu najmniejszego/największego jest algorytm rekurencyjny, korzystający z funkcji min() lub max() wybierające mniejszy/większy element z dwóch liczb. Ten algorytm działa, tak samo jak poprzedni, w czasie O(n), ale wykorzystuje też liniową pamięć. Pamięć liniowa wynika tutaj z konieczności wykonania n wywołań rekurencyjnych.

lista: list[int] = [1, 17, 4, 19, 2, 1, 99, 82, 46]

def min_rec(l: list[int]) -> int:
if len(l) == 0:
return -1
if len(l) == 1:
return l[0]
else:
return min(l[0], min_rec(l[1:]))

Algorytm wykorzystujący sortowanie

Możemy sobie też wyobrazić algorytm, który działa w czasie stałym O(1) na posortowanej liście, lub samym kosztem sortowania w przypadku dowolnej listy. Może być to przydatne w sytuacji, w której i tak potrzebujemy posortowanej listy.

Algorytm o koszcie O(n*log(n)) wykorzystujący funkcję sort() z biblioteki Pythona wygląda następująco:

lista: list[int] = [1, 17, 4, 19, 2, 1, 99, 82, 46]

lista.sort()
minimum: int = lista[0]
maximum: int = lista[-1]