web-dev-qa-db-fra.com

Java séquence de Fibonacci récursive

S'il vous plaît expliquer ce code simple:

public int fibonacci(int n)  {
    if(n == 0)
        return 0;
    else if(n == 1)
      return 1;
   else
      return fibonacci(n - 1) + fibonacci(n - 2);
}

Je suis confondu avec la dernière ligne surtout parce que si n = 5 par exemple, alors fibonacci (4) + fibonacci (3) serait appelé, etc., mais je ne comprends pas comment cet algorithme calcule la valeur à l'indice 5 par ceci méthode. S'il vous plaît expliquer avec beaucoup de détails!

144
Index Hacker

Dans la séquence de fibonacci, chaque élément est la somme des deux précédents. Donc, vous avez écrit un algorithme récursif.

Alors,

fibonacci(5) = fibonacci(4) + fibonacci(3)

fibonacci(3) = fibonacci(2) + fibonacci(1)

fibonacci(4) = fibonacci(3) + fibonacci(2)

fibonacci(2) = fibonacci(1) + fibonacci(0)

Maintenant, vous connaissez déjà fibonacci(1)==1 and fibonacci(0) == 0. Ainsi, vous pouvez ensuite calculer les autres valeurs.

Maintenant,

fibonacci(2) = 1+0 = 1
fibonacci(3) = 1+1 = 2
fibonacci(4) = 2+1 = 3
fibonacci(5) = 3+2 = 5

Et à partir de la séquence fibonacci 0,1,1,2,3,5,8,13,21...., nous pouvons voir que pour 5th element la séquence fibonacci renvoie 5.

Voir ici pour Tutoriel de récursivité .

156
RanRag

Il y a 2 problèmes avec votre code:

  1. Le résultat est stocké dans int, qui ne peut gérer que les 48 premiers nombres de fibonacci, après quoi le bit de remplissage entier moins et le résultat est faux.
  2. Mais vous ne pouvez jamais exécuter fibonacci (50).
    Le code
    fibonacci(n - 1) + fibonacci(n - 2)
    a très tort.
    Le problème est qu’il appelle fibonacci non pas 50 fois mais bien plus.
    Au début, il appelle fibonacci (49) + fibonacci (48),
    next fibonacci (48) + fibonacci (47) et fibonacci (47) + fibonacci (46)
    Chaque fois, la situation de fibonacci (n) s’est aggravée, de sorte que la complexité est exponentielle. enter image description here

L'approche du code non récursif:

 double fibbonaci(int n){
    double prev=0d, next=1d, result=0d;
    for (int i = 0; i < n; i++) {
        result=prev+next;
        prev=next;
        next=result;
    }
    return result;
}
51
chro

Dans le pseudo-code, où n = 5, les opérations suivantes ont lieu:

fibonacci (4) + fibonnacci (3)

Cela se décompose en:

(fibonacci (3) + fibonnacci (2)) + (fibonacci (2) + fibonnacci (1))

Cela se décompose en:

((((fibonacci (2) + fibonnacci (1)) + ((fibonacci (1) + fibonnacci (0))) + ((fibonacci (1) + fibonnacci (0)) + 1))

Cela se décompose en:

(((((fibonacci (1) + fibonnacci (0)) + 1) + ((1 + 0)) + ((1 + 0) + 1))

Cela se décompose en:

((((1 + 0) + 1) + ((1 + 0)) + ((1 + 0) + 1))

Cela se traduit par: 5

Étant donné que la séquence fibonnacci est 1 1 2 3 5 8 ..., le cinquième élément est 5. Vous pouvez utiliser la même méthodologie pour déterminer les autres itérations.

35
Dan Hardiker

La récursion peut parfois être difficile à saisir. Il suffit de l'évaluer sur un morceau de papier pour un petit nombre:

fib(4)
-> fib(3) + fib(2)
-> fib(2) + fib(1) + fib(1) + fib(0)
-> fib(1) + fib(0) + fib(1) + fib(1) + fib(0)
-> 1 + 0 + 1 + 1 + 0
-> 3

Je ne sais pas comment Java évalue cela, mais le résultat sera le même.

11
tim

Vous pouvez également simplifier votre fonction, comme suit:

public int fibonacci(int n)  {
    if (n < 2) return n;

    return fibonacci(n - 1) + fibonacci(n - 2);
}
11
Otavio Ferreira

La plupart des réponses sont bonnes et expliquent le fonctionnement de la récursion dans fibonacci.

Voici une analyse des trois techniques incluant également la récursivité:

  1. pour boucle
  2. Récursion
  3. mémorisation

Voici mon code pour tester les trois:

public class Fibonnaci {
    // Output = 0 1 1 2 3 5 8 13

    static int fibMemo[];

    public static void main(String args[]) {
        int num = 20;

        System.out.println("By For Loop");
        Long startTimeForLoop = System.nanoTime();
        // returns the fib series
        int fibSeries[] = fib(num);
        for (int i = 0; i < fibSeries.length; i++) {
            System.out.print(" " + fibSeries[i] + " ");
        }
        Long stopTimeForLoop = System.nanoTime();
        System.out.println("");
        System.out.println("For Loop Time:" + (stopTimeForLoop - startTimeForLoop));


        System.out.println("By Using Recursion");
        Long startTimeRecursion = System.nanoTime();
        // uses recursion
        int fibSeriesRec[] = fibByRec(num);

        for (int i = 0; i < fibSeriesRec.length; i++) {
            System.out.print(" " + fibSeriesRec[i] + " ");
        }
        Long stopTimeRecursion = System.nanoTime();
        System.out.println("");
        System.out.println("Recursion Time:" + (stopTimeRecursion -startTimeRecursion));



        System.out.println("By Using Memoization Technique");
        Long startTimeMemo = System.nanoTime();
        // uses memoization
        fibMemo = new int[num];
        fibByRecMemo(num-1);
        for (int i = 0; i < fibMemo.length; i++) {
            System.out.print(" " + fibMemo[i] + " ");
        }
        Long stopTimeMemo = System.nanoTime();
        System.out.println("");
        System.out.println("Memoization Time:" + (stopTimeMemo - startTimeMemo));

    }


    //fib by memoization

    public static int fibByRecMemo(int num){

        if(num == 0){
            fibMemo[0] = 0;
            return 0;
        }

        if(num ==1 || num ==2){
          fibMemo[num] = 1;
          return 1; 
        }

        if(fibMemo[num] == 0){
            fibMemo[num] = fibByRecMemo(num-1) + fibByRecMemo(num -2);
            return fibMemo[num];
        }else{
            return fibMemo[num];
        }

    }


    public static int[] fibByRec(int num) {
        int fib[] = new int[num];

        for (int i = 0; i < num; i++) {
            fib[i] = fibRec(i);
        }

        return fib;
    }

    public static int fibRec(int num) {
        if (num == 0) {
            return 0;
        } else if (num == 1 || num == 2) {
            return 1;
        } else {
            return fibRec(num - 1) + fibRec(num - 2);
        }
    }

    public static int[] fib(int num) {
        int fibSum[] = new int[num];
        for (int i = 0; i < num; i++) {
            if (i == 0) {
                fibSum[i] = i;
                continue;
            }

            if (i == 1 || i == 2) {
                fibSum[i] = 1;
                continue;
            }

            fibSum[i] = fibSum[i - 1] + fibSum[i - 2];

        }
        return fibSum;
    }

}

Voici les résultats:

By For Loop
 0  1  1  2  3  5  8  13  21  34  55  89  144  233  377  610  987  1597  2584  4181 
For Loop Time:347688
By Using Recursion
 0  1  1  2  3  5  8  13  21  34  55  89  144  233  377  610  987  1597  2584  4181 
Recursion Time:767004
By Using Memoization Technique
 0  1  1  2  3  5  8  13  21  34  55  89  144  233  377  610  987  1597  2584  4181 
Memoization Time:327031

Par conséquent, nous pouvons voir que la mémorisation est la meilleure en termes de temps et pour les correspondances de boucle étroitement.

Mais la récursivité prend le plus de temps et peut-être devriez-vous éviter dans la vie réelle. De même, si vous utilisez la récursivité, veillez à optimiser la solution.

8
Pritam Banerjee
                                F(n)
                                /    \
                            F(n-1)   F(n-2)
                            /   \     /      \
                        F(n-2) F(n-3) F(n-3)  F(n-4)
                       /    \
                     F(n-3) F(n-4)

Il est important de noter que cet algorithme est exponentiel car il ne stocke pas le résultat des nombres calculés précédemment. Par exemple, F(n-3) est appelé 3 fois.

Pour plus de détails, reportez-vous à l'algorithme de dasgupta chapitre 0.2

8
Amandeep Kamboj

Pour la solution récursive de fibonacci, il est important d’enregistrer la sortie des nombres de fibonacci plus petits, tout en récupérant la valeur d’un nombre plus grand. Cela s'appelle "Mémoizing".

Voici un code qui utilise mémoizing les plus petites valeurs de fibonacci, tout en récupérant un plus grand nombre de fibonacci. Ce code est efficace et ne fait pas plusieurs requêtes de la même fonction.

import Java.util.HashMap;

public class Fibonacci {
  private HashMap<Integer, Integer> map;
  public Fibonacci() {
    map = new HashMap<>();
  }
  public int findFibonacciValue(int number) {
    if (number == 0 || number == 1) {
      return number;
    }
    else if (map.containsKey(number)) {
      return map.get(number);
    }
    else {
      int fibonacciValue = findFibonacciValue(number - 2) + findFibonacciValue(number - 1);
      map.put(number, fibonacciValue);
      return fibonacciValue;
    }
  }
}
5
Amarjit Datta

C'est la meilleure vidéo que j'ai trouvée qui explique complètement la récursivité et la séquence de Fibonacci en Java.

http://www.youtube.com/watch?v=dsmBRUCzS7k

C'est son code pour la séquence et son explication est meilleure que je ne pourrais le faire en essayant de la dactylographier.

public static void main(String[] args)
{
    int index = 0;
    while (true)
    {
        System.out.println(fibonacci(index));
        index++;
    }
}
    public static long fibonacci (int i)
    {
        if (i == 0) return 0;
        if (i<= 2) return 1;

        long fibTerm = fibonacci(i - 1) + fibonacci(i - 2);
        return fibTerm;
    }
5
user2718538

Michael Goodrich et al. Fournissent un algorithme très intelligent dans les structures de données et les algorithmes en Java, permettant de résoudre récursivement fibonacci en temps linéaire en renvoyant un tableau de [fib (n), fib (n-1)].

public static long[] fibGood(int n) {
    if (n < = 1) {
        long[] answer = {n,0};
        return answer;
    } else {
        long[] tmp = fibGood(n-1);
        long[] answer = {tmp[0] + tmp[1], tmp[0]};
        return answer;
    }
}

Cela donne fib (n) = fibGood (n) [0].

4
Rae

Une séquence de Fibbonacci est une séquence qui additionne le résultat d’un nombre lorsqu’elle est ajoutée au résultat précédent en commençant par 1.

      so.. 1 + 1 = 2
           2 + 3 = 5
           3 + 5 = 8
           5 + 8 = 13
           8 + 13 = 21

Une fois que nous comprenons ce que Fibbonacci est, nous pouvons commencer à décomposer le code.

public int fibonacci(int n)  {
    if(n == 0)
        return 0;
    else if(n == 1)
      return 1;
   else
      return fibonacci(n - 1) + fibonacci(n - 2);
}

La première si l'état recherche un cas de base, où la boucle peut éclater. La déclaration else if ci-dessous qui fait la même chose, mais elle pourrait être ré-écrite comme suit ...

    public int fibonacci(int n)  {
        if(n < 2)
             return n;

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

À présent qu’un scénario de base est établi, nous devons comprendre la pile d’appels. Votre premier appel à "fibonacci" sera le dernier à être résolu sur la pile (séquence d’appels) lorsqu’il se résout dans l’ordre inverse. La dernière méthode appelée résout en premier, puis la dernière à être appelée avant celle-ci et ainsi de suite ...

Ainsi, tous les appels sont passés avant que rien ne soit "calculé" avec ces résultats. Avec une entrée de 8, nous attendons une sortie de 21 (voir tableau ci-dessus).

fibonacci (n - 1) continue à être appelé jusqu'à atteindre le cas de base, puis fibonacci (n - 2) jusqu'à ce qu'il atteigne le cas de base. Lorsque la pile commence à additionner le résultat dans l'ordre inverse, le résultat sera comme si ...

1 + 1 = 1        ---- last call of the stack (hits a base case).
2 + 1 = 3        ---- Next level of the stack (resolving backwards).
2 + 3 = 5        ---- Next level of the stack (continuing to resolve).

Ils continuent de bouillonner (résolution arrière) jusqu’à ce que la somme correcte soit renvoyée au premier appel de la pile et c’est ainsi que vous obtiendrez votre réponse.

Cela dit, cet algorithme est très inefficace car il calcule le même résultat pour chaque branche dans laquelle le code se divise. Une approche bien meilleure est une approche "ascendante" dans laquelle aucune mémoisation (mise en cache) ou récursivité (pile d'appels en profondeur) n'est requise.

Ainsi...

        static int BottomUpFib(int current)
        {
            if (current < 2) return current;

            int fib = 1;
            int last = 1;

            for (int i = 2; i < current; i++)
            {
                int temp = fib;
                fib += last;
                last = temp;
            }

            return fib;
        }
3
Jeffrey Ferreiras

dans la séquence fibonacci , les deux premiers éléments sont 0 et 1, chaque autre élément est la somme des deux éléments précédents. c'est à dire:
0 1 1 2 3 5 8 ...

le cinquième élément correspond donc à la somme des quatrième et troisième éléments.

3
yurib

Pourquoi cette réponse est différente

Toute autre réponse soit:

  • Imprime au lieu de retours
  • Fait 2 appels récursifs par itération
  • Ignore la question en utilisant des boucles

(à part: aucun d’entre eux n’est réellement efficace; utilisez formule de Binet pour calculer directement le nth terme)

Fibre récursive

Voici une approche récursive qui évite un appel double-récursif en passant à la fois la réponse précédente ET celle qui précède.

private static final int FIB_0 = 0;
private static final int FIB_1 = 1;

private int calcFibonacci(final int target) {
    if (target == 0) { return FIB_0; }
    if (target == 1) { return FIB_1; }

    return calcFibonacci(target, 1, FIB_1, FIB_0);
}

private int calcFibonacci(final int target, final int previous, final int fibPrevious, final int fibPreviousMinusOne) {
    final int current = previous + 1;
    final int fibCurrent = fibPrevious + fibPreviousMinusOne;
    // If you want, print here / memoize for future calls

    if (target == current) { return fibCurrent; }

    return calcFibonacci(target, current, fibCurrent, fibPrevious);
}
2
AjahnCharles

La plupart des solutions proposées ici fonctionnent en complexité O (2 ^ n). Recalculer des noeuds identiques dans une arborescence récursive est inefficace et gaspille les cycles du processeur.

On peut utiliser la mémoisation pour faire fonctionner la fonction fibonacci dans O(n) temps

public static int fibonacci(int n) {
    return fibonacci(n, new int[n + 1]);
}

public static int fibonacci(int i, int[] memo) {

    if (i == 0 || i == 1) {
        return i;
    }

    if (memo[i] == 0) {
        memo[i] = fibonacci(i - 1, memo) + fibonacci(i - 2, memo);
    }
    return memo[i];
}

Si nous suivons la route de programmation dynamique de bas en haut, le code ci-dessous est assez simple pour calculer fibonacci:

public static int fibonacci1(int n) {
    if (n == 0) {
        return n;
    } else if (n == 1) {
        return n;
    }
    final int[] memo = new int[n];

    memo[0] = 0;
    memo[1] = 1;

    for (int i = 2; i < n; i++) {
        memo[i] = memo[i - 1] + memo[i - 2];
    }
    return memo[n - 1] + memo[n - 2];
}
2
realPK

La réponse RanRag (acceptée) fonctionnera correctement, mais ce n'est une solution optimisée que si et à moins qu'elle soit mémorisée comme expliqué dans la réponse d'Anil.

Pour l’approche récursive ci-dessous, les appels de méthode de TestFibonacci sont au minimum

public class TestFibonacci {

    public static void main(String[] args) {

        int n = 10;

        if (n == 1) {
            System.out.println(1);

        } else if (n == 2) {
            System.out.println(1);
            System.out.println(1);
        } else {
            System.out.println(1);
            System.out.println(1);
            int currentNo = 3;
            calFibRec(n, 1, 1, currentNo);
        }

    }

    public static void calFibRec(int n, int secondLast, int last,
            int currentNo) {
        if (currentNo <= n) {

            int sum = secondLast + last;
            System.out.println(sum);
            calFibRec(n, last, sum, ++currentNo);
        }
    }

}
1
M Sach

Essaye ça

private static int fibonacci(int n){
    if(n <= 1)
        return n;
    return fibonacci(n - 1) + fibonacci(n - 2);
}

Pour plus d’informations, consultez ceci Série de Fibonacci en sortie dans Java - Code médiocre

1
markus rytter

En utilisant un ConcurrentHashMap interne qui pourrait théoriquement permettre à cette implémentation récursive de fonctionner correctement dans un environnement multithread, j'ai implémenté une fonction fib qui utilise à la fois BigInteger et Récursion. Il faut environ 53 ms pour calculer les 100 premiers nombres de fibres.

private final Map<BigInteger,BigInteger> cacheBig  
    = new ConcurrentHashMap<>();
public BigInteger fibRecursiveBigCache(BigInteger n) {
    BigInteger a = cacheBig.computeIfAbsent(n, this::fibBigCache);
    return a;
}
public BigInteger fibBigCache(BigInteger n) {
    if ( n.compareTo(BigInteger.ONE ) <= 0 ){
        return n;
    } else if (cacheBig.containsKey(n)){
        return cacheBig.get(n);
    } else {
        return      
            fibBigCache(n.subtract(BigInteger.ONE))
            .add(fibBigCache(n.subtract(TWO)));
    }
}

Le code de test est:

@Test
public void testFibRecursiveBigIntegerCache() {
    long start = System.currentTimeMillis();
    FibonacciSeries fib = new FibonacciSeries();
    IntStream.rangeClosed(0,100).forEach(p -&R {
        BigInteger n = BigInteger.valueOf(p);
        n = fib.fibRecursiveBigCache(n);
        System.out.println(String.format("fib of %d is %d", p,n));
    });
    long end = System.currentTimeMillis();
    System.out.println("elapsed:" + 
    (end - start) + "," + 
    ((end - start)/1000));
}
 et le résultat du test est: 
. 
. 
. 
. 
. 
 de 93 12200160415121876738 
 Fib de 94 est 19740274219868223167 
 Fib de 95 est 31940434634990099905 [.____] Fib de 96 est 51680708854858323072 
 Fib de 97 est 83621143448828979. 135301852344706746049 
 Fib de 99 est 218922995834555169026 
 Fib de 100 est 354224848179261915075 
 écoulé: 58,0 
 est écoulé.
1
George Curington

Je pense que c'est un moyen simple:

public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        int number = input.nextInt();
        long a = 0;
        long b = 1;
        for(int i = 1; i<number;i++){
            long c = a +b;
            a=b;
            b=c;
            System.out.println(c);
        }
    }
}
1
user3787713

C’est une séquence de base qui affiche ou obtient une sortie de 1 1 2 3 5 8 c’est une séquence dans laquelle la somme du nombre précédent, le nombre actuel, sera affichée ensuite.

Essayez de regarder le lien ci-dessous Java Séquence de Fibonacci récursive Tutoriel

public static long getFibonacci(int number){
if(number<=1) return number;
else return getFibonacci(number-1) + getFibonacci(number-2);
}

Cliquez ici Regardez Java Tutoriel sur la séquence de Fibonacci récursive pour l'alimentation à la cuillère

1
Jaymelson Galang

Voici un febonacci d'une ligne récursif:

public long fib( long n ) {
        return n <= 0 ? 0 : n == 1 ? 1 : fib( n - 1 ) + fib( n - 2 );
}
1
RonTLV

Voici la solution O(1):

 private static long fibonacci(int n) {
    double pha = pow(1 + sqrt(5), n);
    double phb = pow(1 - sqrt(5), n);
    double div = pow(2, n) * sqrt(5);

    return (long) ((pha - phb) / div);
}

formule du nombre de Fibonacci de Binet utilisé pour la mise en œuvre ci-dessus. Pour les grandes entrées, long peut être remplacé par BigDecimal.

0
Samir Agayarov

Utilisez while:

public int fib(int index) {
    int tmp = 0, step1 = 0, step2 = 1, fibNumber = 0;
    while (tmp < index - 1) {
        fibNumber = step1 + step2;
        step1 = step2;
        step2 = fibNumber;
        tmp += 1;
    };
    return fibNumber;
}

L’avantage de cette solution est qu’il est facile de lire et de comprendre le code, en espérant que cela aide

0
Gavriel Cohen
public class febo 
{
 public static void main(String...a)
 {
  int x[]=new int[15];  
   x[0]=0;
   x[1]=1;
   for(int i=2;i<x.length;i++)
   {
      x[i]=x[i-1]+x[i-2];
   }
   for(int i=0;i<x.length;i++)
   {
      System.out.println(x[i]);
   }
 }
}
0
Abhishek Choubey
public class FibonacciSeries {

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int N = scanner.nextInt();
        for (int i = 0; i <= N; i++) {
            int result = fibonacciSeries(i);
            System.out.println(result);
        }
        scanner.close();
    }

    private static int fibonacciSeries(int n) {
        if (n < 0) {
            return 1;
        } else if (n > 0) {
            return fibonacciSeries(n - 1) + fibonacciSeries(n - 2);
        }
        return 0;
    }
}
0
user3231661

Une séquence de Fibbonacci est une séquence qui résume le résultat d'un nombre puis que nous avons ajoutée au résultat précédent, nous devrions commencer à partir de 1. J'essayais de trouver une solution basée sur un algorithme, donc je construis le code récursif, remarquant que je garde numéro précédent et j'ai changé la position. Je cherche la séquence de Fibbonacci de 1 à 15.

public static void main(String args[]) {

    numbers(1,1,15);
}


public static int numbers(int a, int temp, int target)
{
    if(target <= a)
    {
        return a;
    }

    System.out.print(a + " ");

    a = temp + a;

    return numbers(temp,a,target);
}
0
Mathias Stavrou

Pour compléter, si vous voulez pouvoir calculer des nombres plus grands, vous devez utiliser BigInteger.

Un exemple itératif.

import Java.math.BigInteger;
class Fibonacci{
    public static void main(String args[]){
        int n=10000;
        BigInteger[] vec = new BigInteger[n];
        vec[0]=BigInteger.ZERO;
        vec[1]=BigInteger.ONE;
        // calculating
        for(int i = 2 ; i<n ; i++){
            vec[i]=vec[i-1].add(vec[i-2]);
        }
        // printing
        for(int i = vec.length-1 ; i>=0 ; i--){
            System.out.println(vec[i]);
            System.out.println("");
        }
    }
}
0
Tiago Zortea

http://en.wikipedia.org/wiki/Fibonacci_number en plus de détails

public class Fibonacci {

    public static long fib(int n) {
        if (n <= 1) return n;
        else return fib(n-1) + fib(n-2);
    }

    public static void main(String[] args) {
        int N = Integer.parseInt(args[0]);
        for (int i = 1; i <= N; i++)
            System.out.println(i + ": " + fib(i));
    }

}

Faites-en aussi simple que nécessaire sans avoir besoin d'utiliser la boucle While ou autre

0
vikas