Хвостовая Рекурсия Фибоначчи

Как реализовать рекурсивную функцию Фибоначчи без циклов, работающих в O (n)?

4 ответов


обычно я был бы против публикации ответа на вопрос домашней работы, как это, но все, что опубликовано до сих пор, кажется, чрезмерно усложняет вещи. Как сказано в комментариях выше, вы должны просто использовать рекурсию для решения проблемы, как вы сделали бы итеративно.

вот итеративное решение:

def fib(n):
  a, b = 0, 1
  while n > 0:
    a, b = b, a+b
    n -= 1
  return a

вот эквивалентное рекурсивное решение:

def fib(n):
  def fib_help(a, b, n):
    return fib_help(b, a+b, n-1) if n > 0 else a
  return fib_help(0, 1, n)

обратите внимание, что в обоих случаях мы фактически вычисляем до Fn+1, но вернуться Fn как результат. Это хорошо согласуется с" подсказкой", которую вам дали.

Я надеюсь, что вы потратите время, чтобы сравнить два решения и убедить себя, что они эквивалентны. Понимание того, как преобразовать итеративное решение в эквивалентное рекурсивное (или наоборот), является хорошим навыком для развития.


код Scala для нахождения n-го числа Фибоначчи. Для получения дополнительной информации о хвостовой рекурсии http://nerds.logdown.com/posts/1406258-n-th-fibonacci-number

object Main {
     def main(args: Array[String]) {
        println(fib(9));
        println(fib(8));
        println(fib(7));
        println(fib(6));
        println(fib(5));
        println(fib(4));
        println(fib(3));
        println(fib(2));
        println(fib(1));
        println(fib(0));
      }
      def fib(n: Int): Int = {
        def fib(n: Int, p :Int, c: Int): Int ={
          if (n == 0) return -1; // undefined
          if (n == 1) return p;
          fib(n-1, c, p + c)
        }
        fib(n, 0, 1);
      }
    }

чтобы решить эту проблему в линейном времени, необходимо использовать метод динамического программирования, известный как memoization.

алгоритм Фибоначчи в псевдо-код, с помощью мемоизации, выглядит так:

memoryMap[n]

func fib(int n)
    if (n is in memoryMap) then
        return memoryMap[n]
    if (n <= 1) then
        memoryMap[n] = n
    else
        memoryMap[n] = fib(n-1) + fib(n-2)

    return memoryMap[n]

чтобы объяснить, вы после каждого вызова fib (x) вы сохраняете результат в карте памяти. Для каждого последующего вызова все запросы на fib(x) будут бесплатными: то есть поиск результата в памяти стоит только O (1) времени.


в случае если кто-то ищет решение на JavaScript:

function _fib(n, left, right) {
  switch (n) {
    case 0: return 0
    case 1: return right
    default: return _fib(n - 1, right, left + right)
  }
}

function fib(n) {
  return _fib(n, 0, 1)
}

который работает в o(n) времени и O (1) пространстве с оптимизацией хвостового вызова.