Как избежать повторяющихся чисел в рекурсии Python

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

def fibonacci(n):
    if n in (1, 2):
        return 1
    if n in (3,):
        print(3,)

    return fibonacci(n-1) + fibonacci(n-2)


print(fibonacci(10))

Ответы (2 шт):

Автор решения: u111

В данном случае можно сделать это через цикл: при x = 0,1,2 значение возвращается напрямую, а иначе результат получается в цикле.

def fib(x):
    if x == 0:
        return 0
    if x == 1 or x == 2:
        return 1
    a, b = 1, 1
    for i in range(x - 2):
        a, b = b, a + b
    return b
→ Ссылка
Автор решения: Stanislav Volodarskiy

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

(fn, fn+1) = (fn, fn-1 + fn)

Ради ускорения мы поменяли интерфейс функции, она теперь возвращает пару чисел вместо одного. Спрячем подробности реализации за красивым традиционным фасадом:

def fib(n):

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

    return fib(n)[1]

Или вычисления можно делать на аргументах функции, чтобы получить хвостовую рекурсию:

def fib(n):

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

    return fib(n, -1, 1)

Если вспомнить формулы f2n-1 = fn-12 + fn2 и f2n = (2fn-1 + fn)fn, то можно сделать очень быструю рекурсию:

def fib(n):

    def fib(n):
        if n == 0:
            return 1, 0
        if n % 2 == 0:
            a, b = fib(n // 2)
            return a ** 2 + b ** 2, (2 * a + b) * b
        a, b = fib(n - 1)
        return b, a + b

    return fib(n)[-1]
→ Ссылка