Теория
Задача уменьшается до простого случая
Рекурсивная функция вызывает саму себя с более простой версией задачи. Базовый случай даёт ответ без нового вызова, а рекурсивный шаг гарантированно приближает аргумент к нему.
Нужны обе части. Без базового случая вызовы не остановятся; без уменьшения задачи базовый случай может существовать в коде, но никогда не быть достигнут.
def sum_to(number): if number == 0: return 0 return number + sum_to(number - 1)Вызовы сначала углубляются, потом возвращаются
При sum_to(3) первый вызов не знает окончательного ответа, пока не завершится sum_to(2). Цепочка углубляется до нуля, а затем значения возвращаются в обратном порядке.
Для трассировки разделите лист на две части: аргументы при входе и результаты при возврате. Это не смешивает два направления движения.
- Входящие аргументы: 3, 2, 1, 0.
- Базовый вызов с нулём возвращает 0.
- Возвраты собирают 1, затем 3, затем 6.
Та же модель встречается в задачах ЕГЭ
В заданиях с рекурсивной функцией часто нужно не написать код, а аккуратно вычислить значение. Правило остаётся тем же: найдите базовые аргументы, раскройте только нужные вызовы и отдельно соберите возвраты. Если ветвей две, рисуйте небольшое дерево и не считайте один и тот же узел «на глаз» несколько раз.
def f(number): if number <= 1: return 1 return f(number - 1) + f(number - 2)Для f(3) понадобятся f(2) и f(1), а для f(2) — f(1) и f(0). Сначала подпишите обе единицы в базе, затем сложите возвраты снизу вверх: f(2) равно 2, f(3) равно 3.
Базовый случай должен быть достижим
Проверка number == 0 не спасёт функцию, если положительный аргумент на каждом шаге увеличивается. Расстояние до нуля растёт, и цепочка закончится RecursionError.
Как проверять рекурсию
Начните с базового аргумента, затем проверьте один шаг над ним и только после этого разбирайте более длинную цепочку. Для каждого вызова записывайте собственное значение параметра.
- Найдите базовый случай. Запишите его аргумент и немедленный результат.
- Проверьте уменьшение. Сравните аргумент текущего и следующего вызова.
- Раскройте вызовы. Дойдите до базы, не вычисляя возвраты заранее.
- Соберите ответы. Возвращайтесь по цепочке в обратном порядке.
Практика
Найдите базовый случай
При n = 0 функция сразу возвращает 1. Именно этот ответ останавливает цепочку вызовов.
Посчитайте вызовы
Значения n равны 3, 2, 1 и 0. Получается четыре вызова.
Проследите возврат результата
Получается 3 + 2 + 1 + 0 = 6. После базового случая результаты возвращаются в обратном порядке.
Назовите ошибку без остановки
Python ограничивает глубину вызовов. Когда предел исчерпан, возникает `RecursionError`.
Проверьте рекурсивную степень
Вызовы разворачиваются до нуля, затем возвращают 1, 2, 4, 8 и 16.
Итог
Теперь вы можете найти базовый случай, доказать приближение к нему и проследить возврат результата.
Возьмите функцию степени двойки, разверните вызов для аргумента 3 до базы и соберите значения обратно, прежде чем запускать код.
Прогресс
0 / 5Вы ещё не решали задания