<Datenstruktur> Einseitige kreisförmige verkettete Liste

Inhalt

1. Einführung von Beispielen

2. Was ist eine verkettete Liste mit einem Ring?

3. Ideen zur Problemlösung

4. Erweiterungsprobleme

   (1) Langsam macht 1 Schritt auf einmal und schnell macht 2 Schritte auf einmal. Kannst du aufholen?

   (2) Langsam macht 1 Schritt auf einmal, schnell macht 3 Schritte auf einmal, kannst du aufholen? schnell wie wäre es mit 4 Schritten auf einmal? Was ist mit n Schritten?

   (3) Wo ist der Einstiegspunkt der verknüpften Listenschleife?


1. Einführung von Beispielen

  •  Direkte Verbindung:

zirkulär verknüpfte Liste

  • Thema:

2. Was ist eine verkettete Liste mit einem Ring?

 In einer normalen einfach verknüpften Liste ist jeder Knoten der Reihe nach verknüpft, und der letzte Knoten zeigt wie folgt auf NULL:

 Der letzte Knoten der verknüpften Liste mit einem Ring zeigt nicht mehr auf NULL, sondern zeigt auf einen beliebigen vorherigen Knoten, wodurch eine verknüpfte Liste mit einem Ring gebildet wird, und der Zyklus wird fortgesetzt. wie folgt:

3. Ideen zur Problemlösung

Wir können das obige Bild ein wenig abstrahieren: Bevor wir den Ring betreten, verwenden wir eine gerade Linie, um ihn darzustellen, und nachdem wir den Ring betreten haben, verwenden wir einen Kreis, um den Zyklus darzustellen. Diese Frage muss die Idee verwenden, den Zwischenknoten zu finden und den Geschwindigkeitszeiger des letzten k-ten Knotens zu finden, den wir zuvor erklärt haben. Definieren Sie zwei langsame und schnelle Zeiger, die auf den Anfang der Position zeigen. Lassen Sie langsam einen Schritt nach dem anderen machen und schnell zwei Schritte auf einmal.

Wenn langsam auf halbem Weg zur geraden Linie geht, ist schnell nur am Eintrittspunkt des Rings.

 Angenommen, wenn langsam gerade den Eintrittspunkt des Rings erreicht, geht schnell zur nächsten Position, zu welcher Zeit schnell mit dem Aufholmodus beginnt

 schnell beginnt langsam langsam einzuholen, unter der Annahme, dass schnell beginnt langsam langsam an der folgenden Position einzuholen

  • Code zeigen wie folgt:
bool hasCycle(struct ListNode *head) {
    struct ListNode*slow=head;
    struct ListNode*fast=head;
    while(fast&&fast->next)
    {
        slow=slow->next;
        fast=fast->next->next;
        if(slow==fast)
        {
            return true;
        }
    }
    return false;
}

Allein aus der Sicht der Desintegration ist dieses Problem nicht kompliziert. Es kann nur gelöst werden, indem die Idee von schnellen und langsamen Zeigern verwendet wird. Dieses Problem allein kann zu vielen Problemen führen, die unserer Diskussion wert sind, um unsere zu vertiefen Verständnis der zirkulär verketteten Liste Kennen Sie die folgenden drei Erweiterungsprobleme:

4. Erweiterungsprobleme

(1) Langsam macht 1 Schritt auf einmal und schnell macht 2 Schritte auf einmal. Kannst du aufholen?

  •  Antwort: Sicherlich.
  • beweisen:

Wenn langsam in die Mitte geht, muss schnell den Ring betreten und schnell beginnt zu jagen. Wir nehmen an, dass, nachdem Slow in die Schleife eintritt, der Abstand zwischen Slow und Fast N ist. Zu diesem Zeitpunkt macht Slow 1 Schritt und Fast 2 Schritte, und der Abstand zwischen ihnen verkürzt sich um 1 und wird N-1. Und so weiter, jedes Mal, wenn Sie jagen, wird die Entfernung um 1 verringert, und wenn die Entfernung auf 0 verringert wird, werden Sie aufholen. Alles in allem wird es definitiv aufholen.

(2) Langsam macht 1 Schritt auf einmal, schnell macht 3 Schritte auf einmal, kannst du aufholen? schnell wie wäre es mit 4 Schritten auf einmal? Was ist mit n Schritten?

  •  Antwort: nicht unbedingt
  • beweisen:

Lassen Sie uns zuerst die Situation besprechen, in der langsam 1 Schritt auf einmal und schnell 3 Schritte auf einmal macht. Angenommen, langsam macht 1 Schritt, schnell macht 3 Schritte und betritt einfach den Ring, und wenn langsam gerade den Ring betritt, ist schnell möglicherweise 1 Kreis gegangen.Die spezifische Situation hängt von der Größe des Rings ab.Zu diesem Zeitpunkt ist der Abstand zwischen langsam und schnell ist N. und nehmen an, dass die Länge des Rings C ist.

Langsam macht 1 Schritt auf einmal, schnell macht 3 Schritte auf einmal und die Entfernung wird N-2. Es ist ersichtlich, dass jedes Mal, wenn schnell und langsam gefahren wird, die Distanz um 2 verkürzt wird. An diesem Punkt ist es nicht schwer, das herauszufinden. Es muss klassifiziert und diskutiert werden. Wenn N eine gerade Zahl ist, können Sie einfach aufholen. Wenn N eine ungerade Zahl ist, ist die Enddistanz des Jagens -1. At Dieses Mal müssen Sie erneut jagen, was langsam und schnell bedeutet. Der Abstand zwischen ihnen wird zu C-1.

Fahren Sie fort, gemäß der vorherigen Analyse, wenn C-1 eine gerade Zahl ist, dann können Sie aufholen. Wenn C-1 eine ungerade Zahl ist, wird es niemals aufholen, und es wird in einer drahtlosen Schleife gejagt, aber es wird nicht aufholen. Die Differenz N zwischen ihnen wird durch die Länge vor dem Betreten des Rings und die Länge des Rings bestimmt, und diese beiden sind zufällig, daher ist der Wert von N ungewiss, er kann ungerade oder gerade sein, und wenn die Diskussion als gerecht fortgesetzt wird Jetzt wird eine ungerade Zahl für immer verschwunden sein.

Auf die gleiche Weise ist auch das schnelle Gehen von 4 Schritten auf einmal die gleiche Diskussion, was auch nicht unbedingt der Fall ist, aber dieses Mal wird die Entfernung bei jedem Gehen um 3 verkürzt. Wenn N ein Vielfaches von 3 ist, können Sie aufholen. Wenn es kein Vielfaches von 3 ist, müssen Sie die Diskussion fortsetzen. Interessierte Kinderschuhe können weiter lernen. Die Idee ist die gleiche wie schnell 3 Schritte auf einmal zu machen .

(3) Wo ist der Einstiegspunkt der verknüpften Listenschleife?

 Wenn wir die von langsam und schnell zurückgelegte Distanz berechnen, ist der Einstiegspunkt natürlich klar.

  • Gesetz eins:

Langsam macht 1 Schritt auf einmal, schnell macht 2 Schritte auf einmal, dann fährt schnell doppelt so weit wie langsam

Bevor wir das im Detail erklären, müssen wir zunächst einmal klarstellen, dass es nicht so ist, dass der langsame Zeiger langsam darin einen Kreis geht und der schnelle Zeiger schnell den langsamen nicht eingeholt hat, weil schnell 2 nimmt Schritte auf einmal, und langsam macht jeweils 1. Die Entfernung verringert sich jedes Mal um 1, sodass es immer näher und näher kommt, bis es gefangen wird. Höchstens 1 Runde schneller, aber nie genau 1 Runde. So lässt sich leicht ableiten, wie viel langsamer und schneller gegangen sind.

  • Annehmen:
  1. [Listenkopf - - - Einstiegspunkt]: L
  2. [Einstiegspunkt - - - Begegnungspunkt]: X
  3. [Länge des Rings]: C

Von langsam zurückgelegte Strecke: L + X

Schnell zurückgelegte Distanz: L + N*C + X

  • erklären:

Da bereits erwähnt wurde, dass die Langsamen nicht den ganzen Weg gehen und nicht gejagt werden, lässt sich leicht ableiten, dass die Entfernung der Langsamen L+X ist

Wenn sich der schnelle Zeiger jeweils um 2 Schritte bewegt, ist der schnelle Zeiger wahrscheinlich mehrere Male gegangen, bevor der langsame Zeiger den Einstiegspunkt erreicht, weil der Ring zu klein ist. In kurzen 3 Sätzen:

  1. L ist sehr klein, C ist sehr groß, bevor langsam in den Ring eintritt, kann schnell innerhalb des Rings sein und der Kreis ist noch nicht vollendet.
  2. L ist sehr groß, C ist sehr klein, bevor langsam in den Ring eintrat, ging schnell viele Kreise darin
  3. Aber nachdem langsam den Ring betritt, muss schnell innerhalb eines Kreises langsam langsam einholen, und ihr Abstand beträgt höchstens C-1

Nach dem, was eingangs gesagt wurde, ist die zurückgelegte Strecke von schnell doppelt so groß wie die zurückgelegte Strecke von langsam, und die folgende Formel kann aufgeführt werden:

2*(L+X) = L+N*C+X

Nach Vereinfachung: L+X = N*C oder L = N*C - X oder L = (N-1)*C + (CX) oder L + X = N*C

Verwenden Sie diese Formel, um zu beweisen: Ein Zeiger geht von meet, ein Zeiger geht von head, sie treffen sich am Einstiegspunkt!

Da die Formel (N-1)*C angibt, dass nach dem Gehen von N-1 Kreisen vom Treffpunkt zum Treffpunkt zurückgekehrt wird, kehrt zu diesem Zeitpunkt die Entfernung von CX zum Einstiegspunkt zurück, von dem aus gesehen werden kann das obige, dass diese Formel sie zurück zum Einstiegspunkt bringt.

  • Verwenden Sie eine praktische Aufgabe, um die Lage der Ein- und Ausstiegspunkte gezielt zu lösen:
  • Direkte Verbindung:

Circular Linked List 2.0-->Einstiegspunkt finden

  • Thema:

  •  Code zeigen wie folgt:
struct ListNode* detectCycle(struct ListNode* head) {
    struct ListNode* slow = head;
    struct ListNode* fast = head;
    while (fast && fast->next)
    {
        //判断是否是带环链表
        slow = slow->next;
        fast = fast->next->next;
        if (slow == fast)
        {
            struct ListNode* meet = slow;
            while (meet != head)
            {
                //求出相遇点
                meet = meet->next;
                head = head->next;
            }
            return meet;
        }
    }
    return NULL;
}
  • Es gibt eine andere Möglichkeit, den Treffpunkt zu finden:

Nachdem Sie den Treffpunkt gefunden haben, lassen Sie den Treffpunkt das Ende sein, und lassen Sie den nächsten Punkt den Kopf der neuen verknüpften Liste sein

Diese Methode ist besonders raffiniert und führt nur zu dem Problem, die Schnittmenge zweier verknüpfter Listen zu finden. Da sich das Ende der verknüpften Liste headA zu diesem Zeitpunkt trifft und das Ende der verknüpften Liste headB ebenfalls übereinstimmt, bedeutet dies, dass sich die beiden verknüpften Listen schneiden müssen, und der Schnittpunkt ist der Einstiegspunkt Listen ist genau das, was der Blogger im vorherigen Blog-Beitrag ausführlich erläutert hat.Erklärung, hier nicht zu viel Betonung.

Ich denke du magst

Origin blog.csdn.net/bit_zyx/article/details/123819416
Empfohlen
Rangfolge