J'essaie de rappeler un algorithme sur la récursion de Fibonacci. Le suivant:
public int fibonacci(int n) {
if(n == 0)
return 0;
else if(n == 1)
return 1;
else
return fibonacci(n - 1) + fibonacci(n - 2);
}
c'est pas ce que je cherche parce que c'est gourmand. Cela va croître de manière exponentielle (il suffit de regarder séquence Java de Fibonacci récursive - plus l'argument initial est gros, plus les appels inutiles seront faits).
Il y a probablement quelque chose comme un "décalage d'argument cyclique", où l'appel de la valeur Fibonacci précédente récupérera la valeur au lieu de la calculer à nouveau.
peut-être comme ça:
int fib(int term, int val = 1, int prev = 0)
{
if(term == 0) return prev;
return fib(term - 1, val+prev, val);
}
cette fonction est queue récursive. cela signifie qu'il pourrait être optimisé et exécuté de manière très efficace. En fait, il est optimisé dans une simple boucle.
Ce type de problèmes sont de type récurrence linéaire et ils sont résolus plus rapidement via l'exponiation de matrice rapide. Voici le blogpost qui décrit ce type d’approche de manière concise.
Vous pouvez faire une version assez rapide de Fibonacci récursif en utilisant memoization (ce qui signifie: stocker les résultats précédents pour éviter de les recalculer). Par exemple, voici une preuve de concept en Python, dans laquelle un dictionnaire est utilisé pour enregistrer les résultats précédents:
results = { 0:0, 1:1 }
def memofib(n):
if n not in results:
results[n] = memofib(n-1) + memofib(n-2)
return results[n]
Il retourne rapidement pour les valeurs d'entrée qui bloqueraient normalement la version récursive "normale". Gardez simplement à l'esprit qu'un type de données int
ne suffira pas pour conserver des résultats volumineux et qu'il est recommandé d'utiliser des entiers à précision arbitraire.
Une option totalement différente - réécrire cette version itérative ...
def iterfib(n):
a, b = 0, 1
for i in xrange(n):
a, b = b, a + b
return a
... en tant que fonction queue récursive, appelée loop
dans mon code:
def tailfib(n):
return loop(n, 0, 1)
def loop(i, a, b):
if i == 0:
return a
return loop(i-1, b, a+b)
J'ai trouvé un article intéressant sur le problème de fibonacci
ici l'extrait de code
# Returns F(n)
def fibonacci(n):
if n < 0:
raise ValueError("Negative arguments not implemented")
return _fib(n)[0]
# Returns a Tuple (F(n), F(n+1))
def _fib(n):
if n == 0:
return (0, 1)
else:
a, b = _fib(n // 2)
c = a * (2 * b - a)
d = b * b + a * a
if n % 2 == 0:
return (c, d)
else:
return (d, c + d)
# added iterative version base on C# example
def iterFib(n):
a = 0
b = 1
i=31
while i>=0:
d = a * (b * 2 - a)
e = a * a + b * b
a = d
b = e
if ((n >> i) & 1) != 0:
c = a + b;
a = b
b = c
i=i-1
return a
Imaginons que vous souhaitiez avoir le nième nombre puis créez un tableau contenant les nombres précédents
int a[n];
a[0] = 0;
a[1] =1;
a[i] = n[i-1]+n[n-2];
Un exemple en JavaScript utilisant la récursivité et un cache initialisé paresseux pour une efficacité accrue:
var cache = {};
function fibonacciOf (n) {
if(n === 0) return 0;
if(n === 1) return 1;
var previous = cache[n-1] || fibonacciOf(n-1);
cache[n-1] = previous;
return previous + fibonacciOf(n-2);
};
l'algorithme de duedl0r traduit en swift:
func fib(n: Int, previous: (Int, Int) = (0,1)) -> Int {
guard n > 0 else { return 0 }
if n == 1 { return previous.1 }
return fib(n - 1, previous: (previous.1, previous.0 + previous.1))
}
exemple travaillé:
fib(4)
= fib(4, (0,1) )
= fib(3, (1,1) )
= fib(2, (1,2) )
= fib(1, (2,3) )
= 3
Vous devez mémoriser la valeur calculée pour arrêter la croissance exponentielle.
Voici un exemple de travail pour une récursivité plus rapide en utilisant la mémoire.
Un bon algorithme pour les calculs rapides de fibonacci est (en python):
def fib2(n):
# return (fib(n), fib(n-1))
if n == 0: return (0, 1)
if n == -1: return (1, -1)
k, r = divmod(n, 2) # n=2k+r
u_k, u_km1 = fib2(k)
u_k_s, u_km1_s = u_k**2, u_km1**2 # Can be improved by parallel calls
u_2kp1 = 4 * u_k_s - u_km1_s + (-2 if k%2 else 2)
u_2km1 = u_k_s + u_km1_s
u_2k = u_2kp1 - u_2km1
return (u_2kp1, u_2k) if r else (u_2k, u_2km1)
def fib(n):
k, r = divmod(n, 2) # n=2k+r
u_k, u_km1 = fib2(k)
return (2*u_k+u_km1)*(2*u_k-u_km1)+(-2 if k%2 else 2) if r else u_k*(u_k+2*u_km1)
Si vous avez besoin d'un calcul très rapide, créez un lien vers libgmp et utilisez les fonctions mpz_fib_ui () ou mpz_fib2_ui ().