Come osserva Ariel , l'algoritmo standard di massima ricerca riportato di seguito:
def find_maximum(a):
m = a[0]
for x in a:
if x > m: m = x
return m
funzionerà infatti senza modifiche purché:
- qualsiasi coppia di elementi può essere confrontata, e
- si garantisce che l'input contenga un elemento massimo, ovvero un elemento che è coppia maggiore di qualsiasi altro elemento nell'input.
(Il primo presupposto sopra può effettivamente essere rilassato, anche senza dover modificare l'algoritmo, purché ipotizziamo che l'elemento massimo sia comparabile con ogni altro elemento e che x > y
sia sempre falso se gli elementi x
e y
sono incomparabili).
In particolare, afferma che:
[…] Per essere certi di una risposta, l'elemento deve essere esplicitamente confrontato con ogni altro elemento (perché il confronto non è transitivo).
non è vero sotto i presupposti di cui sopra. Infatti, per dimostrare che l'algoritmo sopra troverà sempre l'elemento massimo, è sufficiente osservare che:
- poiché il ciclo scorre su tutti gli elementi di input, in alcune iterazioni
x
sarà l'elemento massimo;
- poiché l'elemento massimo è di coppia maggiore di ogni altro elemento, ne consegue che, al termine di tale iterazione,
m
sarà l'elemento massimo; e
- poiché nessun altro elemento può essere più grande della coppia dell'elemento massimo, ne consegue che
m
non cambierà in nessuna delle iterazioni successive.
Pertanto, alla fine del ciclo, m
sarà sempre l'elemento massimo, se l'input ne contiene uno.
Ps. Se l'ingresso non non necessariamente contengono sempre un elemento massimale, quindi verificare che infatti sarà davvero richiederà testare la risposta candidato contro ogni altro elemento per verificare che sia realmente massima. Tuttavia, possiamo ancora farlo in O ( n ) tempo dopo aver eseguito l'algoritmo di ricerca massima sopra:
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
(Suppongo qui che la relazione >
sia irreflessiva, cioè nessun elemento può essere maggiore di se stesso. In caso contrario, il confronto x > m
nel passaggio 2 dovrebbe essere sostituito con x ≠ m and x > m
, dove ≠
indica il confronto di identità. Oppure potremmo semplicemente applicare l'ottimizzazione indicato di seguito.)
Per dimostrare la correttezza di questa variazione dell'algoritmo, considerare i due possibili casi:
- Se l'input contiene un elemento massimo, il passaggio 1 lo troverà (come mostrato sopra) e il passaggio 2 lo confermerà.
- Se l'ingresso lo fa non contiene un elemento massimo, il passaggio 1 finirà per selezionare alcuni elementi arbitrari come
m
. Non importa quale sia, dal momento che in ogni caso non sarà massimo, quindi il passaggio 2 lo rileverà e tornerà None
.
Se abbiamo memorizzato l'indice m
nella matrice di ingresso a
, si potesse davvero passo ottimizzare 2 per controllare solo quegli elementi che vengono prima m
a a
, dal momento che tutti gli elementi successivi sono già stati rispetto a m
al punto 1. Ma questa ottimizzazione non cambia il tempo di complessità asintotica dell'algoritmo, che è ancora O ( n ).