Heim Backend-Entwicklung C#.Net-Tutorial Es stellt sich heraus, dass die Fibonacci-Folge auch so geschrieben ist, wussten Sie das?

Es stellt sich heraus, dass die Fibonacci-Folge auch so geschrieben ist, wussten Sie das?

Jul 27, 2018 am 10:49 AM
c#

Auf Baidu gibt es viele Antworten auf „Nicht-rekursives Schreiben von Fibonacci“, aber sie sind nicht zufriedenstellend. Erstens ist es zu schwer zu verstehen, und zweitens ist die Leistung ungefähr die gleiche wie bei der Rekursion.

Wenn es um die Fibonacci-Folge geht, egal ob Sie ein unerfahrener Programmierer oder ein technischer Veteran sind, fällt Ihnen als Erstes definitiv die rekursive Schreibmethode ein. Der Unterschied zwischen technischen Veteranen und Programmierneulingen besteht darin, dass sie darüber nachdenken, die Ergebnisse der Rekursion zu speichern, um wiederholte Berechnungen zu reduzieren. Dies sind sehr häufige Operationen, aber haben Sie jemals darüber nachgedacht, dass die Fibonacci-Folge auch nicht rekursiv geschrieben werden kann?
Auf Baidu gibt es viele Antworten auf „Nicht-rekursives Schreiben von Fibonacci“, aber erstens ist es zu schwer zu verstehen, und zweitens ist die Leistung in etwa die gleiche wie bei der Rekursion. Am Anfang wollte ich auch selbst eines schreiben, solange es den Aufrufstapel rekursiver Aufrufe simuliert, aber diese Idee ist etwas selbstverständlich und das geschriebene Programm ist auch sehr kompliziert. Was zu tun? Zu diesem Zeitpunkt kann sich die Tiefendurchquerung des Baums als nützlich erweisen.
Zuerst definieren wir die Baumknoten:
public class Node
        {
            public Node(long value, bool visited)
            {
                Value = value;
                Visited = visited;
            }

            public long Value { get; set; }//存放结点的值
            public bool Visited { get; set; }
        }
Nach dem Login kopieren

Dann können wir gerne lernen, wie man den DFS-Stack schreibt

  public static long Fblc(int n)
        {
            Stack<Node> s = new Stack<Node>();
            s.Push(new Node(n, false));
            long sum = 0;
            long[] childrenResultMemo = new long[n+1];
            childrenResultMemo[0] = 1;
            childrenResultMemo[1] = 1;
            //long children = 0;
            while (s.Any())
            {
                var cur = s.Pop();
             
                    if (cur.Visited == false)
                    {
                        if (childrenResultMemo[cur.Value] == 0)
                        {
                            cur.Visited = true;
                            if (childrenResultMemo[cur.Value - 1] != 0 && childrenResultMemo[cur.Value - 2] != 0)
                            {
                                var result = childrenResultMemo[cur.Value - 1] + childrenResultMemo[cur.Value - 2];
                                childrenResultMemo[cur.Value] = result;
                                sum += result;
                                s.Push(cur);
                            }
                            else
                            {
                                s.Push(cur);
                                s.Push(new Node(cur.Value - 1, false));
                                s.Push(new Node(cur.Value - 2, false));
                            }
                        }
                        else
                        {
                            sum += childrenResultMemo[cur.Value];//保存子树结果的优化,会有个特殊情况要处理
                        }
                        
                    }
                   
                
            }

            return sum;
        }
Nach dem Login kopieren

Die Kernidee des obigen Algorithmus besteht darin, den zu durchlaufen stapeln und den Stapel herausnehmen. Wenn das oberste Element besucht wurde (besucht ist wahr), überspringen Sie es (der obige Code verwendet die Optimierung zum Speichern von Teilbaumergebnissen, es muss ein Sonderfall behandelt werden, der unten detailliert beschrieben wird); andernfalls ist die besuchte Markierung des aktuellen übergeordneten Knotens wahr, was bedeutet, dass er besucht und auf den Stapel verschoben wurde. Anschließend werden alle seine untergeordneten Knoten auf den Stapel verschoben.

Wenn Sie dieser Idee folgen, wird der Code, den Sie schreiben, nicht so aussehen wie oben. Die Codemenge wird jedoch viel kleiner und präziser sein. Die Komplexität des Algorithmus wird jedoch der von rekursiv ähneln Schreiben, da es wiederholte Berechnungen geben wird.

Was sollen wir also tun? Es gibt nur eine Lösung: Raum gegen Zeit austauschen und die Ergebnisse des Teilbaums speichern. Wenn der entsprechende Teilbaum berechnet wurde und Ergebnisse vorliegen, werden wir die Tiefe nicht mehr durchqueren die nächste Ebene verwenden. Wir speichern die Ergebnisse des Teilbaums in einem Array:

long[] childrenResultMemo = new long[n+1];
Nach dem Login kopieren

Wenn der Teilbaum normalerweise bereits Ergebnisse enthält, hätte logischerweise darauf zugegriffen werden müssen. Allerdings gibt es Sonderfälle, bei denen Teilbaum 0 und Teilbaum 1 am Anfang stehen:

childrenResultMemo[0] = 1;
childrenResultMemo[1] = 1;
Nach dem Login kopieren

Sammeln Sie einfach die Ergebnisse in den Zweigen dieses Sonderfalls: Wie wäre es mit

sum += childrenResultMemo[cur.Value];
Nach dem Login kopieren

, ist das so? Methode, oder? Selten? Tatsächlich ähnelt der Bewertungsprozess der Fibonacci-Folge einer Tiefendurchquerung des Baums. Solange es sich also um die Implementierung der Tiefendurchquerung handelt, ist dies durchaus machbar.

Verwandte Artikel:

Beispiel für Python-Druck einer Fibonacci-Sequenz

PHP implementiert Fibonacci-Sequenz

Verwandte Videos :

Datenstruktur-Abenteuer – Warteschlangenkapitel

Das obige ist der detaillierte Inhalt vonEs stellt sich heraus, dass die Fibonacci-Folge auch so geschrieben ist, wussten Sie das?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn

Heiße KI -Werkzeuge

Undresser.AI Undress

Undresser.AI Undress

KI-gestützte App zum Erstellen realistischer Aktfotos

AI Clothes Remover

AI Clothes Remover

Online-KI-Tool zum Entfernen von Kleidung aus Fotos.

Undress AI Tool

Undress AI Tool

Ausziehbilder kostenlos

Clothoff.io

Clothoff.io

KI-Kleiderentferner

AI Hentai Generator

AI Hentai Generator

Erstellen Sie kostenlos Ai Hentai.

Heiße Werkzeuge

Notepad++7.3.1

Notepad++7.3.1

Einfach zu bedienender und kostenloser Code-Editor

SublimeText3 chinesische Version

SublimeText3 chinesische Version

Chinesische Version, sehr einfach zu bedienen

Senden Sie Studio 13.0.1

Senden Sie Studio 13.0.1

Leistungsstarke integrierte PHP-Entwicklungsumgebung

Dreamweaver CS6

Dreamweaver CS6

Visuelle Webentwicklungstools

SublimeText3 Mac-Version

SublimeText3 Mac-Version

Codebearbeitungssoftware auf Gottesniveau (SublimeText3)

Active Directory mit C# Active Directory mit C# Sep 03, 2024 pm 03:33 PM

Leitfaden zu Active Directory mit C#. Hier besprechen wir die Einführung und die Funktionsweise von Active Directory in C# sowie die Syntax und das Beispiel.

C#-Serialisierung C#-Serialisierung Sep 03, 2024 pm 03:30 PM

Leitfaden zur C#-Serialisierung. Hier besprechen wir die Einführung, die Schritte des C#-Serialisierungsobjekts, die Funktionsweise bzw. das Beispiel.

Zufallszahlengenerator in C# Zufallszahlengenerator in C# Sep 03, 2024 pm 03:34 PM

Leitfaden zum Zufallszahlengenerator in C#. Hier besprechen wir die Funktionsweise des Zufallszahlengenerators, das Konzept von Pseudozufallszahlen und sicheren Zahlen.

C#-Datenrasteransicht C#-Datenrasteransicht Sep 03, 2024 pm 03:32 PM

Leitfaden zur C#-Datenrasteransicht. Hier diskutieren wir die Beispiele, wie eine Datenrasteransicht aus der SQL-Datenbank oder einer Excel-Datei geladen und exportiert werden kann.

Muster in C# Muster in C# Sep 03, 2024 pm 03:33 PM

Leitfaden zu Mustern in C#. Hier besprechen wir die Einführung und die drei wichtigsten Arten von Mustern in C# zusammen mit ihren Beispielen und der Code-Implementierung.

Primzahlen in C# Primzahlen in C# Sep 03, 2024 pm 03:35 PM

Leitfaden zu Primzahlen in C#. Hier besprechen wir die Einführung und Beispiele von Primzahlen in C# sowie die Codeimplementierung.

Fakultät in C# Fakultät in C# Sep 03, 2024 pm 03:34 PM

Leitfaden zur Fakultät in C#. Hier diskutieren wir die Einführung in die Fakultät in C# zusammen mit verschiedenen Beispielen und Code-Implementierungen.

Der Unterschied zwischen Multithreading und asynchronem C# Der Unterschied zwischen Multithreading und asynchronem C# Apr 03, 2025 pm 02:57 PM

Der Unterschied zwischen Multithreading und Asynchron besteht darin, dass Multithreading gleichzeitig mehrere Threads ausführt, während asynchron Operationen ausführt, ohne den aktuellen Thread zu blockieren. Multithreading wird für rechenintensive Aufgaben verwendet, während asynchron für die Benutzerinteraktion verwendet wird. Der Vorteil des Multi-Threading besteht darin, die Rechenleistung zu verbessern, während der Vorteil von Asynchron nicht darin besteht, UI-Threads zu blockieren. Die Auswahl von Multithreading oder Asynchron ist von der Art der Aufgabe abhängt: Berechnungsintensive Aufgaben verwenden Multithreading, Aufgaben, die mit externen Ressourcen interagieren und die UI-Reaktionsfähigkeit asynchron verwenden müssen.

See all articles