Если вы только начали изучать рекурсию, это кажется таким запутанным и сложным. Но если вы разберете его шаг за шагом и попытаетесь понять, что происходит под капотом, вы поймете это. Как только вы его получите, он навсегда останется с вами;).
Так что же такое рекурсия простыми словами?
Это процесс, в котором функция вызывает сама себя. Другими словами, вы вызываете одну и ту же функцию с разными значениями на каждой итерации, пока не достигнете базового случая. Это также означает, что вам всегда нужен базовый вариант для использования рекурсии.
Теперь вопрос: каков базовый случай рекурсии?
По сути, базовый случай - это условие, которое вы используете для остановки функции. Без базового случая ваша функция будет бесконечно зацикливаться, что нехорошо.
Один из известных примеров использования рекурсии - поиск факториала (!).
n! = n × (n−1)!, where 0! = 1. To find 4! we need to find 3! then 2! then 1! 4! = 4 × 3! 3! = 3 × 2!; 2! = 2 × 1!; 1! = 1 4! = 4 × 3 × 2 × 1 => 24
Вот решение для поиска факториала с использованием рекурсии:
function factorial(num){ //base case of recursion to stop calling itself if(num === 1 || num === 0) return 1; //recursivly calling itself with new value return num * factorial(num - 1) } factorial(4) // => 24
Рекурсия имеет временную сложность O (n) и пространственную сложность O (n).
Теперь давайте попробуем понять, что происходит на каждой итерации нашей функции, например, factorial (4). Если считать 4! ответ - 24, поэтому функция должна вернуть 24.
Используя отладчик в браузере, мы можем проверять значение num при каждом вызове.
Вызов №1, num = 4, тогда наша функция должна вызвать сама себя со значением num-1.
function factorial(4){ //base case of recursion to stop calling itself if(4 === 1 || 4 === 0) return 1; // =>false return 4 * factorial(3) }
Тогда факториал (4) приостановлен, пока мы получаем результат из факториала (3).
Вызов # 2, факториал (3) вызывает факториал (2), и он приостановлен, пока мы получаем результат из факториала (2).
function factorial(3){ if(3 === 1 || 3 === 0) return 1; // => false return 3 * factorial(2) }
Вызов №3, факториал (2) на удержании после вызова факториала (1).
function factorial(2){ if(2 === 1 || 2 === 0) return 1; // => false return 2 * factorial(1) }
Вызов №4, последним вызовом был factorial (1), вызванный возвратом 1, так как базовый случай был установлен так.
function factorial(1){ if(1 === 1 || 1=== 0) return 1; // => true return 1 * factorial(0) } // => 1
Давайте представим, что происходит под капотом, когда мы вызываем factorial (4).
//Visualization of invoking function factorial(4) function factorial(4){ //base case of recursion to stop calling itself if(4 === 1 || 4 === 0) return 1; // => false return 4 * factorial(3){ // => 4 * 3 * 2 * 1 if(3 === 1 || 3 === 0) return 1; // => false return 3 * factorial(2){ // => 3 * 2 * 1 if(2 === 1 || 4 === 0) return 1; return 2 * factorial(1){ // => 2 * 1 if(1 === 1 || 1 === 0) return 1; // => true return 1 * factorial(0)} } } } // factorial(4) = 4 * factorial(3) = 4 * (3 * factorial(2)) = // 4 * (3 *(2 * factirial(1))) = 4 * (3 * (2 * (1))) = // 4 * (3 * (2)) = 4 * (6) = 24 // => 4 * 3 * 2 * 1 => 24
factorial (4) = 4 * 3 * 2 * 1 = 24, правильный ответ.
Как видите, функция рекурсии создает n временных значений, пока не достигнет базового случая. Как только итерация находится в базовом случае, сохраненные значения используются для вычисления ответа.
Нерекурсивное решение для поиска факториала может использовать итерацию цикла:
function factorial(num){ let result = 1; if(num === 0) return 1; while(num){ result = result * num; num--; } return result; }
Здесь временная сложность O (n); Сложность пространства - O (1).
Рекурсия требует меньше строк кода за счет используемого пространства. Так что рекурсия не годится, если вам небезразлично пространство. Итак, в зависимости от ситуации вы должны решить использовать рекурсию или нет.
Надеюсь, этот пост поможет вам разобраться в рекурсии. Буду признателен за любые отзывы!
Ресурсы с более подробной информацией:
Факториал!
Примеры: мы обычно говорим (например) 4! как «4-факторный, но некоторые люди говорят 4 крика или 4 удара. Мы можем легко… www.mathsisfun.com »