← до розділу

Фібоначчі: дерево викликів

fib(n) = fib(n−1) + fib(n−2). Наївна рекурсія знову й знову рахує те саме, а мемоізація запам'ятовує вже знайдені значення. Порівняйте, скільки викликів потрібно в обох випадках.

перше обчислення fib(k)повторне обчисленняузято з пам'ятіпоточний виклик

Дерево викликів

Ріст кількості викликів

наївна: 2·fib(n+1) − 1мемоізація: 2n − 1

Як рахує модель

fib(0) = 0, fib(1) = 1 – база, далі fib(n) = fib(n−1) + fib(n−2).
Наївна рекурсія: викликів C(n) = C(n−1) + C(n−2) + 1, звідси C(n) = 2·fib(n+1) − 1 ≈ 1,6n – експонента.
Мемоізація: перед обчисленням дивимось у словник memo. Кожне fib(k) рахується один раз, тож викликів 2n − 1 – лінійно.
Дерево будується в тому порядку, у якому виконується програма: спершу вся ліва гілка fib(n−1), потім права.

Що спробувати

Чому так?

Наївна рекурсія не пам'ятає результатів: щоб знайти fib(n−1), вона заново рахує fib(n−2), хоча його доведеться рахувати й у сусідній гілці. Повторні гілки (червоні) займають більшу частину дерева, і з кожним n дерево стає майже в 1,6 раза більшим.

Мемоізація – найпростіша форма динамічного програмування: «розв'язав підзадачу – запиши відповідь». Пам'ять O(n) обмінюємо на час: замість мільйонів викликів – десятки.

Шкільна програма: інформатика, 9–11 клас (рекурсія, складність алгоритмів, динамічне програмування).