Если вы просто пытаетесь ускорить свой рекурсивный алгоритм, может быть достаточно запоминания . Это метод хранения результатов вызовов функций, чтобы будущие вызовы с теми же параметрами могли просто повторно использовать результат. Это применимо, если (и только если) ваша функция
- не имеет побочных эффектов и
- зависит только от его параметров (т.е. не от какого-то состояния).
Это сэкономит вам время, если (и только если) функция вызывается с одними и теми же параметрами снова и снова. Популярные примеры включают в себя рекурсивное определение чисел Фибоначчи, то есть
f(0)f(1)f(n+2)=0=1=f(n+1)+f(n), n≥0
Если оценивать наивно, то вызывается экспоненциально часто. С запоминанием, всегда вычислялось уже , таким образом, остается только линейное количество вызовов.f ( n ) f ( n + 1 )ff(n)f(n+1)
Обратите внимание, что, напротив, запоминание почти бесполезно для таких алгоритмов, как сортировка слиянием: обычно несколько (если таковые имеются) частичных списков идентичны, а проверки на равенство стоят дорого (сортировка только немного дороже!).
В практических реализациях то, как вы сохраняете результаты, имеет большое значение для производительности. Использование хеш-таблиц может быть очевидным выбором, но может нарушить локальность. Если ваши параметры являются неотрицательными целыми числами, массивы являются естественным выбором, но могут вызвать огромные накладные расходы памяти, если вы используете только некоторые записи. Следовательно, запоминание - это компромисс между эффектом и стоимостью; окупится ли это, зависит от вашего конкретного сценария.
Динамическое программирование - это совершенно другой зверь. Это применимо к проблемам с собственностью, которая
- его можно разбить на подзадачи (возможно, несколькими способами),
- эти подзадачи могут быть решены независимо,
- (оптимальные) решения этих подзадач можно объединить с (оптимальными) решениями исходной задачи и
- подзадачи имеют одно и то же свойство (или являются тривиальными).
Обычно это подразумевается, когда люди используют принцип оптимальности Беллмана .
Теперь, это только описывает класс проблем, которые могут быть выражены определенным видом рекурсии. Оценка их (часто) эффективна, потому что запоминание может быть применено с большим эффектом (см. Выше); обычно меньшие подзадачи возникают как часть многих более крупных проблем. Популярные примеры включают расстояние редактирования и алгоритм Беллмана-Форда .