← Все вопросы

Что такое динамическое программирование? Фибоначчи с мемоизацией

Задан 17 месяцев назад806 просмотров3 ответа
17

Все пугают «динамическим программированием». Звучит страшно. Можете показать суть на Фибоначчи — почему обычная рекурсия медленная и как мемоизация её ускоряет?

3 ответа

28
✓ Принятый ответ — помог автору

Суть динамики проще, чем название: если задача распадается на одинаковые подзадачи, которые ты считаешь по многу раз — посчитай каждую ОДИН раз и запомни ответ. Это и есть мемоизация.

Наивный Фибоначчи пересчитывает одни и те же значения экспоненциально много раз:

def fib(n):
    if n < 2:
        return n
    return fib(n - 1) + fib(n - 2)
# fib(40) уже считается заметно долго

Добавляем кеш — и сложность падает с O(2^n) до O(n):

from functools import lru_cache

@lru_cache(maxsize=None)
def fib(n):
    if n < 2:
        return n
    return fib(n - 1) + fib(n - 2)
# fib(100) — мгновенно

Вот и весь фокус: «запоминай уже посчитанное». Дальше идёт вариант снизу-вверх (таблицей), но идея та же.

Ivan Ivanov @да, memo = {}; if n in memo: return memo[n] и т.д. · 17 месяцев назад
Евгений Костенко lru_cache одной строкой — магия 😄 · 17 месяцев назад
Алиса Сергеева а без декоратора как? через словарь руками? · 17 месяцев назад
12

Снизу-вверх без рекурсии вообще, O(n) времени и O(1) памяти:

def fib(n):
    a, b = 0, 1
    for _ in range(n):
        a, b = b, a + b
    return a

Для Фибоначчи это самый практичный вариант.

6

ДП = «разбей на подзадачи + не считай дважды». Всё.

Ваш ответ

Войдите, чтобы ответить на вопрос.
Поддержать проект