Como señala Ariel , el algoritmo estándar de búsqueda máxima que figura a continuación:
def find_maximum(a):
m = a[0]
for x in a:
if x > m: m = x
return m
de hecho funcionará sin modificaciones siempre que:
- se puede comparar cualquier par de elementos, y
- se garantiza que la entrada contiene un elemento máximo, es decir, un elemento que es mayor en pares que cualquier otro elemento en la entrada.
(La primera suposición anterior en realidad puede estar relajado, incluso sin tener que modificar el algoritmo, el tiempo que se supone que el elemento de máxima es comparable con cualquier otro elemento y que x > y
siempre es falsa si los elementos x
y y
son incomparable.)
En particular, su afirmación de que:
[…] Para estar seguro de una respuesta, el elemento debe compararse explícitamente con cualquier otro elemento (porque la comparación no es transitiva).
no es cierto bajo los supuestos dados anteriormente. De hecho, para demostrar que el algoritmo anterior siempre encontrará el elemento máximo, es suficiente observar que:
- dado que el ciclo itera sobre todos los elementos de entrada, en alguna iteración
x
será el elemento máximo;
- Como el elemento máximo es por pares mayor que cualquier otro elemento, se deduce que, al final de esa iteración,
m
será el elemento máximo; y
- dado que ningún otro elemento puede ser mayor en pares que el elemento máximo, se deduce que
m
no cambiará en ninguna de las iteraciones posteriores.
Por lo tanto, al final del ciclo, m
siempre será el elemento máximo, si la entrada contiene uno.
PD. Si la entrada no siempre contiene necesariamente un elemento máximo, entonces verificar ese hecho requerirá probar la respuesta del candidato contra cualquier otro elemento para verificar que es realmente máxima. Sin embargo, todavía podemos hacer eso en O ( n ) tiempo después de ejecutar el algoritmo de búsqueda máxima anterior:
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
(Asumo aquí que la relación >
es irreflexiva, es decir, ningún elemento puede ser mayor que sí mismo. Si ese no es necesariamente el caso, la comparación x > m
en el paso 2 debería reemplazarse x ≠ m and x > m
, donde ≠
denota la comparación de identidad. O simplemente podríamos aplicar la optimización anotado abajo.)
Para probar la exactitud de esta variación del algoritmo, considere los dos casos posibles:
- Si la entrada contiene un elemento máximo, entonces el paso 1 lo encontrará (como se muestra arriba) y el paso 2 lo confirmará.
- Si la entrada no contiene un elemento máximo, entonces el paso 1 terminará eligiendo algún elemento arbitrario como
m
. No importa qué elemento sea, ya que en cualquier caso no será máximo, y por lo tanto, el paso 2 lo detectará y volverá None
.
Si almacenamos el índice de m
la matriz de entrada a
, que en realidad podría optimizar el paso 2 solamente para comprobar los elementos que vienen antes m
de a
, ya que todos los elementos posteriores ya se han comparado con m
en el paso 1. Sin embargo, esta optimización no cambia el tiempo de complejidad asintótica del algoritmo, que sigue siendo O ( n ).