Si solo busca acelerar su algoritmo recursivo, la memorización podría ser suficiente. Esta es la técnica de almacenar resultados de llamadas a funciones para que las llamadas futuras con los mismos parámetros puedan reutilizar el resultado. Esto es aplicable si (y solo si) su función
- no tiene efectos secundarios y
- solo depende de sus parámetros (es decir, no de algún estado).
Le ahorrará tiempo si (y solo si) se llama a la función con los mismos parámetros una y otra vez. Los ejemplos populares incluyen la definición recursiva de los números de Fibonacci, es decir
f(0)f(1)f(n+2)=0=1=f(n+1)+f(n), n≥0
Cuando se evalúa ingenuamente, se llama exponencialmente a menudo. Con la memorización, siempre ha sido calculada por , por lo que solo queda un número lineal de llamadas.f ( n ) f ( n + 1 )ff(n)f(n+1)
Tenga en cuenta que, por el contrario, la memorización es casi inútil para algoritmos como el tipo de fusión: por lo general, pocas (si las hay) listas parciales son idénticas, y las comprobaciones de igualdad son caras (¡la clasificación es solo un poco más costosa!).
En implementaciones prácticas, la forma en que almacena los resultados es de gran importancia para el rendimiento. El uso de tablas hash puede ser la opción obvia, pero puede romper la localidad. Si sus parámetros son enteros no negativos, las matrices son una opción natural, pero pueden causar una sobrecarga de memoria enorme si usa solo algunas entradas. Por lo tanto, la memorización es una compensación entre efecto y costo; si vale la pena depende de su escenario específico.
La programación dinámica es una bestia completamente diferente. Es aplicable a problemas con la propiedad que
- se puede dividir en subproblemas (probablemente en más de una forma),
- esos subproblemas se pueden resolver de forma independiente,
- Las soluciones (óptimas) de esos subproblemas se pueden combinar con las soluciones (óptimas) del problema original y
- Los subproblemas tienen la misma propiedad (o son triviales).
Esto suele estar implícito (implícitamente) cuando las personas invocan el Principio de Optimidad de Bellman .
Ahora, esto solo describe una clase de problemas que pueden expresarse mediante un cierto tipo de recursión. La evaluación de estos es (a menudo) eficiente porque la memorización se puede aplicar con gran efecto (ver arriba); por lo general, los subproblemas más pequeños ocurren como parte de muchos problemas más grandes. Los ejemplos populares incluyen la distancia de edición y el algoritmo Bellman-Ford .