Dowód wykrycia początku cyklu w liście połączonej [duplikat]

To pytanie ma już odpowiedź tutaj:

Z kilku postów wewnątrz stackoverflow i na zewnątrz, dowiedziałem się, jak wykryć cykle na połączonej liście, długość cyklu. Znalazłem również metodę wykrywania początku pętli.

Oto kroki ponownie w celach informacyjnych.

Wykrywanie Pętli:

Mają dwa wskaźniki, klasycznie nazywane Zając i żółw. Przesuń zająca o 2 kroki i żółwia o 1. Jeśli spotykają się w pewnym momencie, to z pewnością istnieje cykl, a miejsce spotkania jest oczywiście wewnątrz cyklu.

Znajdowanie długości pętli:

Utrzymuj jeden wskaźnik w punkcie spotkania, a drugi zwiększ, aż znów będą takie same. Zwiększ licznik, a wartość licznika na meet będzie długość cyklu.

Znajdź początek cyklu

Weź jeden wskaźnik na początek listy, a drugi na miejscu spotkania. Teraz przyrost zarówno o jeden, jak i punkt spotkania jest początkiem pętli. Zweryfikowałem metodę, używając kilku przypadków na papierze, ale nie rozumiem, dlaczego powinna działać.

Czy ktoś może przedstawić matematyczny dowód na to, dlaczego ta metoda działa?

Author: Joel Coehoorn, 2010-10-17

6 answers

Możesz uprościć dowód "Znajdź początek cyklu", jeśli nie używasz meeting point.
Niech drugi wskaźnik zacznie się nie w "miejscu spotkania", ale M krok przed pierwszym wskaźnikiem. (Gdzie M jest długością pętli.)

W ten sposób dowód jest dość oczywisty. Gdy pierwszy wskaźnik osiągnie początek pętli, drugi będzie dokładnie M krok do przodu: również na początku pętli.
 17
Author: Nikita Rybak,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-10-17 10:27:53

Jeśli reprezentujesz listę za pomocą wskaźnika do jej pierwszego węzła (list)

Tutaj wpisz opis obrazka

Algorytm wykrywania pętli jest opisany następująco:

  1. Zadeklaruj Dwa wskaźniki ( pFast) i (pSlow).
  2. Make pSlow and pFast point to list.
  3. Until ( pSlow), (pFast) lub oba wskazują na NULL:
    1. Tutaj wpisz opis obrazka
    2. Tutaj wpisz opis obrazka
    3. If Tutaj wpisz opis obrazka, then STOP as a loop has just been znaleziono.
  4. Jeśli ten punkt został osiągnięty (jeden lub oba wskaźniki są NULL), to nie ma pętli na liście.

Przyjmijmy, że algorytm ten jest poprawny. W tym schemacie sytuacja pętli jest reprezentowana przez następujący diagram:

Tutaj wpisz opis obrazka

Zauważ, jak każdy węzeł, z wyjątkiem tego wskazującego na początek pętli, jest oznaczony liczbą jego celu minus jeden. Jeśli więc jeden węzeł jest oznaczony i i nie jest początkiem pętli, następnie jest wskazywany jako następny element przez węzeł oznaczony symbolem i-1 .

Algorytm opisany powyżej może być opisany jako pętla, ponieważ jego główny krok (3) jest zbiorem pod-kroków, które powtarzają się do momentu spełnienia warunku wyjścia. To zmusza nas do reprezentowania pFast i pSlow w funkcji numeru iteracji w wykonaniu algorytmu (t ).

Tutaj wpisz opis obrazka

Gdyby lista nie miała pętli, pozycje wskaźników byłyby opisane w funkcja t jako:

Tutaj wpisz opis obrazka

Istnieje jednak węzeł, w którym zaczyna się pętla i ta funkcja kończy opisując ewolucję wskaźników. Zakładając, że wskaźnik ten jest oznaczony m , że pętla zawiera węzły (to jest Tutaj wpisz opis obrazka i Tutaj wpisz opis obrazka) i ustawiając t=0 jako wartość iteracji, gdy Tutaj wpisz opis obrazka wtedy:

Tutaj wpisz opis obrazka

Jeśli jeden wskaźnik rzeczywiście wystarczy do wykrycia pętli za pomocą opisanego algorytmu, to musi istnieć przynajmniej rozwiązanie równania Tutaj wpisz opis obrazka.

To równanie jest prawdziwe wtedy i tylko wtedy, gdy istnieje wartość dla t, która sprawia, że:

Tutaj wpisz opis obrazka

Kończy się to funkcją, Tutaj wpisz opis obrazka, która generuje wartości t, które są poprawnymi rozwiązaniami równania opisanego powyżej:

Tutaj wpisz opis obrazka

Tutaj wpisz opis obrazka

W ten sposób udowodniono, że jeden wolny wskaźnik i jeden szybki wskaźnik wystarczą do wykrycia warunków pętli w połączonej liście.

 34
Author: Pablo Francisco Pérez Hidalgo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-04-17 07:01:01

Dystans pokonany przez slowPointer przed spotkaniem = x + y

Dystans pokonany przez fastpointera przed spotkaniem = (x + y + z) + y = x + 2y + z

Ponieważ fastPointer porusza się z podwójną prędkością slowpointera, a czas jest stały dla obu, gdy dotrze do miejsca spotkania.

Więc używając prostej relacji prędkości, czasu i odległości 2 (x+y)= x + 2Y + z = > x+2Y+z = 2x+2Y = > x=z

Stąd poprzez przesunięcie slowpointera na początek listy linked i zrobienie zarówno slowpointera jak i fastPointer do poruszania się po jednym węźle na raz, oba mają taką samą odległość do pokonania .

Osiągną punkt, w którym pętla zaczyna się na liście połączonej.

Schemat dowodu

 5
Author: user5449813,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-10-15 14:56:59

Nie sądzę, że to prawda, że kiedy się spotykają, to punkt wyjścia. Ale tak, jeśli drugi wskaźnik(F) był wcześniej w miejscu spotkania , niż ten wskaźnik będzie na końcu pętli zamiast na początku pętli, a wskaźnik (Y), który rozpoczął się od początku listy, skończy się na początku pętli. dla np:

Tutaj wpisz opis obrazka

Start f tak szybko i S tak wolno, że kończą spotkanie o 9 . Teraz, gdy zacznę S Od początku, to osiągnie w początek pętli tj. 7 ale f będzie na 16 ..

Proszę dać mi znać, jeśli się mylę

 0
Author: MrA,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-08-16 01:27:59

Druga część, stwierdzająca, że "aby znaleźć początek pętli, po prostu przesuń jeden wskaźnik z powrotem do początku listy, a następnie powtarzaj oba, aż się spotkają" jest błędna!

Jest poprawne tylko jeśli szybki wskaźnik okrążył pętlę dokładnie raz - tzn. że część przed rozpoczęciem pętli jest krótsza niż długość pętli - ale jeśli jest dłuższa, algorytm nie działa; możesz utknąć w nieskończonej pętli.

Spróbuj z połączoną listą z 11 pierwiastki, gdzie 11. wskazuje na 7.:

1 1 -> 3 2 -> 5 3 -> 7 4 -> 9 5 -> 11 6 -> 8 7 -> 10 8 -> 7 9 -> 9 9

-- loop detected

Przesuń jeden z powrotem, aby rozpocząć i zwiększyć je: 1 9 -> 2 10 -> 3 11 -> 4 7 -> 5 8 -> 6 9 -> 7 10 -> 8 11 -> 9 7 -> 10 8 -> 11 9 -> 7 10 -> 8 11 ->...

 0
Author: PaulJ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-02-09 12:03:22
/* Algorithm : P2 is moving through the list twice as fast as P1.
   If the list is circular, it will eventually get around P1 and meet */

public boolean hasCycle()
{
  DoubleNode p1,p2;
  p1=p2=firstNode;    //Start with the first loop

  try
  {
    while (p2 != null)     //If p2 reaches end of linked list, no cycle exists
    {
        p1=p1.next;   //Move to next
        p2=p2.next.next; //Move to 2 steps next
        if(p1==p2)
           return true;     //p1 and p2 met, so this means that there is a cycle
    }
  }
  catch(NullPointerException npe)
  {
      //This means that p2 could not move forward
      return false;
  }

  return false;
}
 -1
Author: SHIVA,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-11-28 08:42:08