Динамическое программирование (ДП) — это приём для задач, которые распадаются на перекрывающиеся подзадачи. Идея проста: если одну и ту же подзадачу приходится решать много раз, посчитайте её один раз и сохраните ответ. Это превращает «медленный» экспоненциальный перебор в быстрый линейный.
Классический пример боли — наивные числа Фибоначчи. fib(n) = fib(n-1) + fib(n-2) пересчитывает одни и те же значения снова и снова, и для n=40 уже заметно тормозит. Посмотрим, почему.
f3 считается дважды, f2 — трижды. Подзадачи перекрываются.
▶ fib-slow.py
Мемоизация (top-down)
Мемоизация — это «ДП сверху вниз»: оставляем привычную рекурсиюПриём, при котором функция вызывает саму себя. Нужен базовый случай, чтобы вызовы завершились., но заводим кэш (словарьКоллекция пар «ключ → значение»: {"a": 1}. Быстрый доступ по ключу. По-английски dict.). Перед вычислением проверяем: если ответ для n уже посчитан — возвращаем готовый. Так каждая подзадача решается ровно один раз.
▶ fib-memo.py
💡Совет
Готовый инструмент. В Python есть декоратор @lru_cache из модуля functools — он добавляет мемоизацию автоматически, без ручного словаря. Достаточно навесить его на функциюИменованный блок кода, который можно вызывать многократно. Может принимать аргументы и возвращать результат.. На собеседовании полезно знать оба способа: и ручной кэш, и @lru_cache.
▶ lru.py
💡Совет
Предскажите вывод. Функция считает число способов подняться по лестнице из n ступеней, шагая по 1 или 2 за раз. Это снова Фибоначчи! Сколько способов для n = 4?
▶ predict-stairs.py
Вернётся 5. Способы для 4 ступеней: 1+1+1+1, 1+1+2, 1+2+1, 2+1+1, 2+2. Чтобы попасть на ступень n, мы пришли либо с (n-1) шагом в 1, либо с (n-2) шагом в 2 — отсюда сумма двух предыдущих.
⚠️ Частые ошибки новичков
Ошибка. Сделать memo аргументом по умолчанию в виде memo={}. Мутабельное значение по умолчанию создаётся один раз и сохраняется между вызовами — кэш «протечёт» из одного вызова в другой и даст неверные результаты при разных задачах. Правильно: memo=None и создавать словарь внутри. Запустите пример с протекающим кэшем.
▶ broken-memo.py
Заданиерешение.py
Напишите функцию climb(n) с мемоизацией: число способов подняться на n ступеней шагами по 1 или 2. climb(1)=1, climb(2)=2.
Заданиерешение.py
Дан список монет и сумма. Напишите min_coins(coins, amount) — минимальное число монет, чтобы набрать сумму (монеты можно брать сколько угодно). Если нельзя — верните -1. Используйте мемоизацию.
❓Проверь себя
Что такое мемоизация?
Когда ДП вообще применимо?
Какой декоратор добавляет автоматическую мемоизацию?
ℹ️Важно
✅ Что вы узнали
ДП решает задачи с перекрывающимися подзадачами.
Мемоизация — рекурсия + кэш (top-down).
@lru_cache добавляет кэш автоматически.
Не используйте мутабельный аргументЗначение, которое передаётся функции при вызове. Внутри функции оно доступно как параметр. по умолчанию для кэша.
Комментарии
Загрузка…
Загрузка комментариев…