Хватит пытаться отслеживать все через рекурсивные вызовы и думать о рекурсивной функции как о фактической функции. Иногда случается так, что ты сам себя называешь. Когда вы передаете функции аргумент, вам не нужно знать, что происходит за стеной. Функция - это абстракция для выполняемой работы, которая возвращает правильный ответ на основе своего аргумента. Например, когда вы используете exp()
или log()
или cos()
, вам не нужно знать, как это работает на самом деле, чтобы использовать его.
Именно здесь вы должны совершить рекурсивный скачок веры - «Если я могу доверять этой функции, чтобы дать мне правильный ответ для более мелкой проблемы, то я могу составить ответ для моей текущей проблемы». Для факториалов правильный ответ - 1 для n
, равный нулю или единице, и n * factorial(n - 1)
для n > 1
. Вы можете подтвердить это, написав эту формулировку для небольшого случая:
4! = 4 * 3! = 4 * (3 * 2!) = 4 * (3 * (2 * 1!)) = 4 * (3 * (2 * 1))
Да, это в значительной степени арифметическое определение 4!
Теперь посмотрите на рекурсивную реализацию, которую вы разместили, слегка переупорядоченную, и посмотрите прямую корреспонденцию:
long factorial(long a) { // If I trust this function...
if (a <= 1) // when a is 0 or 1
return 1; // I know the answer is 1.
else // Otherwise, trust the answer for the smaller case of (a-1) and
return (a * factorial(a-1)); // multiply that answer by a to get a!.
}
Если вы готовы совершить этот рекурсивный прыжок веры, тогда многие очень сложные функции практически пишут сами.