Algoritma deteksi siklus Floyd | Menentukan titik awal siklus

32

Saya mencari bantuan untuk memahami algoritma pendeteksian siklus Floyd. Saya telah membaca penjelasan di wikipedia ( http://en.wikipedia.org/wiki/Cycle_detection#Tortoise_and_hare )

Saya dapat melihat bagaimana algoritma mendeteksi siklus dalam waktu O (n). Namun, saya tidak dapat memvisualisasikan fakta bahwa setelah kura-kura dan kelinci bertemu untuk pertama kalinya, permulaan siklus dapat ditentukan dengan menggerakkan penunjuk kura-kura kembali untuk memulai dan kemudian memindahkan kura-kura dan kelinci satu langkah pada satu waktu. Titik pertemuan pertama mereka adalah awal siklus.

Dapatkah seseorang membantu dengan memberikan penjelasan, semoga berbeda dari yang ada di wikipedia, karena saya tidak dapat memahami / memvisualisasikannya?

Anurag Kapur
sumber
3
Saya menemukan jawabannya di stackoverflow. Terima kasih jika ada yang mencari ini untuk saya. Dan bagi mereka yang menyukai saya ingin penjelasan, silakan merujuk ke: stackoverflow.com/questions/3952805/… Jawaban yang dipilih untuk pertanyaan itu, jelaskan!
Anurag Kapur
Hai @Anagag. Sekadar informasi Anda, saya sudah melakukan posting blog pada algoritma "Tortoise and the Hare" di sini
Kyle
Apakah Anda tahu mengapa fastvariabel, atau "kelinci" perlu bergerak dua kali lebih cepat dari kura-kura, bukan hanya satu di depan?
devdropper87
Dijelaskan dengan baik dengan program: javabypatel.blogspot.in/2015/12/detect-loop-in-linked-list.html
Jayesh

Jawaban:

47

Anda dapat merujuk ke "Mendeteksi awal loop dalam daftar yang ditautkan sendiri" , berikut adalah kutipannya:

masukkan deskripsi gambar di sini

Jarak yang ditempuh slowPointersebelum pertemuan =x+y

fastPointer =(x+y+z)+y

Karena fastPointerperjalanan dengan kecepatan dua kali lipatslowPointer , dan waktu adalah konstan untuk keduanya ketika mencapai titik pertemuan. Jadi dengan menggunakan hubungan kecepatan, waktu dan jarak yang sederhana ( slowPointermenempuh setengah jarak):

2dist(slowPointer)=dist(fastPointer)2(x+y)=x+2y+z2x+2y=x+2y+zx=z

Oleh karena itu dengan bergerak slowPointeruntuk memulai daftar tertaut, dan membuat keduanya slowPointerdan fastPointeruntuk memindahkan satu simpul pada satu waktu, mereka berdua memiliki jarak yang sama untuk menutupi .

Mereka akan mencapai pada titik di mana loop dimulai pada daftar yang ditautkan.

Biksu tua
sumber
2
Di sini Anda telah membuat asumsi bahwa mereka akan bertemu setelah satu putaran. Mungkin ada kasus (di mana siklusnya kecil) di mana mereka mungkin bertemu setelah no tertentu. rotasi.
Navjot Waraich
1
@JotWaraich gambar tidak mewakili semua kasus; Namun logikanya masih berlaku
denis631
3
ini adalah jawaban paling langsung tentang algoritma ini di seluruh Internet
Marshall X
7

Saya telah melihat jawaban yang diterima sebagai bukti di tempat lain juga. Namun, meskipun mudah untuk grok, itu tidak benar. Apa buktinya

x=z

Apa yang benar-benar ingin Anda buktikan adalah (menggunakan variabel yang sama seperti yang dijelaskan dalam diagram pada jawaban yang diterima di atas):

z=x mod (y+z)

(y+z)L

jadi, yang ingin kita buktikan adalah:

z=x mod L

Atau z itu kongruen dengan x (modulo L)

Bukti berikut lebih masuk akal bagi saya:

M=x+y

2(x+y)=M+kLkx+yL

x+y=kL

x=kLy

xLyMx+y

Sekali lagi
sumber