Jak zauważa Ariel , standardowy algorytm maksymalnego wyszukiwania podany poniżej:
def find_maximum(a):
m = a[0]
for x in a:
if x > m: m = x
return m
będzie działać bez modyfikacji, o ile:
- dowolna para elementów może być porównywana, oraz
- wejście gwarantuje, że zawiera maksymalny element, tj. element, który jest parowany większy niż jakikolwiek inny element na wejściu.
(Pierwsze założenie powyżej rzeczywiście mogą zostać złagodzone, nawet bez konieczności modyfikacji algorytmu, o ile założymy, że element ilość jest porównywalna z każdym innym pierwiastkiem, a które x > y
jest zawsze fałszywy jeśli elementy x
i y
są nieporównywalne.)
W szczególności twoje twierdzenie, że:
[…] Dla pewności odpowiedzi element musi zostać wyraźnie porównany z każdym innym elementem (ponieważ porównanie nie jest przechodnie).
nie jest prawdą przy powyższych założeniach. W rzeczywistości, aby udowodnić, że powyższy algorytm zawsze znajdzie element maksymalny, wystarczy zauważyć, że:
- ponieważ pętla iteruje wszystkie elementy wejściowe, w pewnym
x
momencie iteracja będzie elementem maksymalnym;
- ponieważ maksymalny element jest parami większy niż każdy inny element, wynika z tego, że pod koniec tej iteracji
m
będzie elementem maksymalnym; i
- ponieważ żaden inny element nie może być większy parą niż element maksymalny, wynika z tego,
m
że nie zmieni się on w żadnej z kolejnych iteracji.
Dlatego na końcu pętli m
zawsze będzie maksymalny element, jeśli wejście zawiera jeden.
Ps. Jeśli wejście jest nie koniecznie zawsze zawiera element maksymalny, a następnie weryfikacji tego faktu będzie rzeczywiście wymaga testowania odpowiedź kandydata przed każdym innym elemencie, aby upewnić się, że jest to naprawdę maksymalne. Jednak nadal możemy to zrobić w czasie O ( n ) po uruchomieniu algorytmu maksymalnego wyszukiwania powyżej:
def find_maximum_if_any(a):
# step 1: find the maximum, if one exists
m = a[0]
for x in a:
if x > m: m = x
# step 2: verify that the element we found is indeed maximal
for x in a:
if x > m: return None # the input contains no maximal element
return m # yes, m is a maximal element
(Zakładam tutaj, że relacja >
jest nierefleksyjna, tzn. Żaden element nie może być większy od siebie. Jeśli nie jest to koniecznie, porównanie x > m
w kroku 2 powinno zostać zastąpione przez x ≠ m and x > m
, gdzie ≠
oznacza porównanie tożsamości. Lub możemy po prostu zastosować optymalizację zanotowano poniżej.)
Aby udowodnić poprawność tej odmiany algorytmu, rozważ dwa możliwe przypadki:
- Jeśli dane wejściowe zawierają maksymalny element, krok 1 go znajdzie (jak pokazano powyżej), a krok 2 to potwierdzi.
- Jeśli dane wejściowe nie zawierają elementu maksymalnego, wówczas krok 1 zakończy wybieranie dowolnego elementu jako
m
. Nie ma znaczenia, który to element, ponieważ w każdym razie nie będzie on maksymalny, a zatem krok 2 wykryje to i wróci None
.
Gdybyśmy przechowywany indeks m
w tablicy wejściowej a
, mogliśmy rzeczywiście zoptymalizować krok 2, aby sprawdzić tylko te elementy, które przychodzą przed m
się a
, ponieważ wszelkie późniejsze elementy zostały już w porównaniu z m
w kroku 1. Ale to optymalizacja nie zmienia czasu złożoności asymptotycznej algorytmu, który wciąż jest O ( n ).