Ist es möglich, den n-ten Term einer Fibonacci-Sequenz unter Verwendung einer definitiven for-Schleife zu finden?

7

Ich verwende das Buch Einführung in die Informatik von John Zelle und werde am Ende von Kapitel 3 (Rechnen mit Zahlen) gebeten, den n-ten Term einer Fibonacci-Sequenz zu finden, wobei vermutlich eine definitive for-Schleife verwendet wird, wie keine andere Entscheidung Struktur wurde noch eingeführt.

Ist das möglich? Ich habe alles versucht, was mir einfiel.

** Ich weiß, wie man es mit if-Anweisungen und dergleichen löst. Aber das Buch hat noch keine Entscheidungsstrukturen behandelt, aber es fordert mich auf, den n-ten Begriff (vom Benutzer angegeben) zu finden. Ich kann also nur davon ausgehen, dass ich weiß, wie man dies mit "for" -Schleifen macht, da dies alles ist, was bisher behandelt wurde

qzxt
quelle
1
Was bedeutet "definitiv für Schleife"?
Keith Thompson
Grundsätzlich eine gezählte Schleife. ZB nehme ich den n-ten Term als Eingabe und sage für i im Bereich (Eingabe):
qzxt
Ich könnte ifAnweisungen entfernen , indem ich die bedingten Ausdrücke in for-Schleifen verschiebe, aber das wäre meiner Meinung nach nur ein völlig nutzloser Hack.
Toniedzwiedz
Also bin ich nicht verrückt und es gibt wirklich keine Möglichkeit, dies ohne Bedingungen zu tun?
qzxt
@qzxt nicht, wenn Sie ungültige Eingaben abfangen möchten, nein.
Toniedzwiedz

Antworten:

11

Wenn es nur das dritte Kapitel ist, bezweifle ich, dass die Autoren die dynamische Programmierung behandelt haben, aber ich werde veranschaulichen, was passiert, wenn eine for-Schleife zur Berechnung der Fibonacci-Zahl .nthFn

Erinnern Sie sich an die Definition,

Fn={0n=01n=1Fn1+Fn2otherwise

Wir könnten dies naiv mit einer rekursiven Funktion berechnen, die in Python definiert ist als:

def fib(n):
    if n < 2:
        return n
    else:
        return fib(n - 1) + fib(n - 2)

Durch mehrmaliges Neuberechnen desselben Unterproblems benötigt diese Funktion jedoch exponentielle Zeit für die Berechnung (siehe Abbildung unten)! fibtree

Es gibt jedoch eine Lösung. Wir können dynamische Programmierung verwenden, um eine "intelligentere" Rekursion durchzuführen und unsere vorherigen Ergebnisse beizubehalten. Auf diese Weise müssen wir F_i nicht neu . Unser Funktionsaufruf "Baum" wird zu einer Liste zusammenfallen und von unten nach oben berechnen . FiFnfib2

def fib2(n):
    if n < 2:
        return n
    else:
        if not results[n]:
            results[n] = fib2(n - 1) + fib2(n - 2)
        return results[n]

Jetzt haben wir unseren , um zu berechnen , aber wenn Sie bemerken, benötigen wir zusätzlichen Platz (einen Punkt im Array für jedes ). Dies kann auf zusätzlichen Platz werden, da jedes nur zwei andere Fibonacci-Zahlen benötigt, nämlich und .O(n)FnO(n)FiO(1)FiFi1Fi2

def fib3(n):
    if n < 2:
        return n
    f_0 = 0
    f_1 = 1
    f_n = 0
    for _ in range(n - 1):
        f_n = f_0 + f_1
        f_0 = f_1
        f_1 = f_n


    return f_n
Nicholas Mancuso
quelle
2
Wow, tolle Antwort! Beachten Sie, dass es einfach ist, dies in eine Form zu bringen, die mit der primitiven Rekursion kompatibel ist, dh in allgemeinen Definitionen herunterzuzählen, indem Sie innerhalb der (Countdown-) Schleife verwenden. ni
Raphael
10

Wenn Sie nur eine for-Schleife verwenden müssen, die iteriert, bis die n-te Fibonacci-Zahl gefunden wird, können Sie Folgendes verwenden:

int fib(int n)
{
    int p = 0;
    int c = 1;
    int r = 0; // The result is initialized to 0 (undefined). 
    for (int i = 0; i < n; i++)
    {
        r = p + c; // Produce next number in the sequence.
        p = c;     // Save previous number.
        c = r;     // Save current number.
    }

    return r;
}

HINWEIS

In der obigen Lösung gehe ich davon aus, dass die Fibonacci-Sequenz 1 1 2 3 5 8 13 ... ist und dass n den Bereich 1, 2, 3, ... hat, da es unter diesen Annahmen keine Fibonacci-Zahl für n <1 gibt Die Funktion gibt eine 0 für n <1 zurück, um anzuzeigen, dass der Eingabeparameter außerhalb des Bereichs liegt (siehe Toms Vorschläge in den Kommentaren unten).

Giorgio
quelle
Die Ausgabe für 0 sollte 0 sein, andernfalls eine gute, einfache und präzise Antwort.
Toniedzwiedz
Es hängt davon ab, wie Sie zählen, tatsächlich sollte fib für n <1 undefiniert sein. Oder meinen Sie, dass 0 undefiniert darstellt und fib (n) daher für alle n <1 0 zurückgeben sollte?
Giorgio
Das stimmt, es kommt darauf an. Wenn wir 0 einschließen, sollte die Ausgabe 0 sein. Wenn wir sie ausschließen, sollte die Funktion einen speziellen Wert zurückgeben, um eine ungültige Eingabe anzuzeigen, was auch für negative Zahlen erfolgen sollte ... aber das OP akzeptiert keine bedingten Ausdrücke. viel weniger Ausnahmen werfen, also denke ich, dass es in Ordnung ist, wie es ist.
Toniedzwiedz
2
@Giorgio Mathematisch ist die Fibonacci-Sequenz für perfekt definiert ; Nichts hindert Sie daran, die Sequenz rückwärts auszuführen und zu invertieren , um - oder , . n<0fn+1=fn+fn1fn1=fn+1fngn=fngn+1=gn1gn
Steven Stadnicki