Comme le note Ariel , l'algorithme de recherche de maximum standard donné ci-dessous:
def find_maximum(a):
m = a[0]
for x in a:
if x > m: m = x
return m
fonctionnera en fait sans modification tant que:
- n'importe quelle paire d'éléments peut être comparée, et
- l'entrée est garantie pour contenir un élément maximal, c'est-à-dire un élément qui est par paire plus grand que tout autre élément dans l'entrée.
(La première hypothèse ci-dessus peut en fait être assouplie, même sans avoir à modifier l'algorithme, tant que nous supposons que l'élément maximal est comparable à tous les autres éléments et cela x > y
est toujours faux si les éléments x
et y
sont incomparables.)
En particulier, vous affirmez que:
[…] Pour être certain d'une réponse, l'élément doit être explicitement comparé à tous les autres éléments (car la comparaison n'est pas transitive).
n'est pas vrai dans les hypothèses données ci-dessus. En fait, pour prouver que l'algorithme ci-dessus trouvera toujours l'élément maximal, il suffit de constater que:
- puisque la boucle itère sur tous les éléments d'entrée, à une certaine itération
x
sera l'élément maximal;
- puisque l'élément maximal est deux par deux plus grand que tout autre élément, il s'ensuit qu'à la fin de cette itération,
m
il sera l'élément maximal; et
- Puisqu'aucun autre élément ne peut être deux par deux plus grand que l'élément maximal, il s'ensuit que
m
cela ne changera sur aucune des itérations suivantes.
Par conséquent, à la fin de la boucle, m
sera toujours l'élément maximal, si l'entrée en contient un.
Ps. Si l'entrée ne contient pas nécessairement toujours un élément maximal, la vérification de ce fait nécessitera en effet de tester la réponse candidate par rapport à tous les autres éléments pour vérifier qu'elle est vraiment maximale. Cependant, nous pouvons toujours le faire en temps O ( n ) après avoir exécuté l'algorithme de recherche de maximum ci-dessus:
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
(Je suppose ici que la relation >
est irréflexive, c'est-à-dire qu'aucun élément ne peut être supérieur à lui-même. Si ce n'est pas nécessairement le cas, la comparaison x > m
de l'étape 2 devrait être remplacée par x ≠ m and x > m
, où ≠
dénote une comparaison d'identité. Ou nous pourrions simplement appliquer l'optimisation noté ci-dessous.)
Pour prouver l'exactitude de cette variation de l'algorithme, considérons les deux cas possibles:
- Si l'entrée contient un élément maximal, alors l'étape 1 le trouvera (comme indiqué ci-dessus) et l'étape 2 le confirmera.
- Si l'entrée ne contient pas d'élément maximal, alors l'étape 1 finira par choisir un élément arbitraire comme
m
. Peu importe de quel élément il s'agit, car il sera en tout cas non maximal, et donc l'étape 2 le détectera et le retournera None
.
Si nous stockons l'indice m
dans le tableau d'entrée a
, on pourrait en fait pas optimize 2 pour vérifier que les éléments qui viennent avant m
dans a
, puisque les éléments ultérieurs ont déjà été comparé à l' m
étape 1. Mais cette optimisation ne change pas la complexité du temps asymptotique de l'algorithme, qui est toujours O ( n ).