フロイドのサイクル検出アルゴリズム| サイクルの開始点の決定


32

私はフロイドのサイクル検出アルゴリズムを理解する助けを求めています。ウィキペディア(http://en.wikipedia.org/wiki/Cycle_detection#Tortoise_and_hare)の説明を読みました

アルゴリズムがO(n)時間でサイクルを検出する方法を見ることができます。ただし、亀とウサギのポインターが初めて会った後、亀のポインターを最初に戻し、亀とウサギの両方を一度に動かすことで、サイクルの開始を決定できるという事実を視覚化することはできません。彼らが最初に会うポイントは、サイクルの始まりです。

私がそれを理解/視覚化できないので、誰かが説明を提供することで助けてくれますか?


3
私はstackoverflowで答えを見つけました。誰かが私のためにこれを探していたらありがとう。そして、私のような人が説明をしたい場合は、stackoverflow.com / questions / 3952805 / …を参照してください。
アヌラグカプール

こんにちは@Anurag。ご参考までに、ここで
カイル

fast変数、または「うさぎ」が1つだけではなく、亀の2倍の速度で移動する必要がある理由を知っていますか?
devdropper87

プログラムでわかりやすく
Jayesh

回答:


47

「一重リンクリストでのループの開始の検出」を参照できます。以下に抜粋を示します。

ここに画像の説明を入力してください

slowPointer会議前に移動した距離 =x+y

fastPointer会議前に移動した距離 = x + 2y + z=(x+y+z)+y

以来fastPointerと共に移動二重の速度slowPointer、および時定数である両方の場合到達ミーティングポイントのため。そのため、単純な速度、時間、距離の関係を使用して(slowPointer距離の半分で移動します):

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

したがって移動によってslowPointerリンクされたリストの開始との両方を作製するslowPointerと、fastPointer一度に1つのノードを移動させるために、それらの両方がカバーに同じ距離を有します

リンクリストでループが開始するポイントに到達します。


2
ここでは、1回転後に会うと仮定しています。一定のノーの後に会うかもしれないケースがあります(サイクルが小さい場合)。回転の。
Navjot Waraich

1
@JotWaraich画像はすべてのケースを代表するものではありません。ただし、ロジックはまだ保持しています
denis631

3
これは、インターネット全体でこのアルゴリズムについての最も単純な答えである
マーシャルX

7

私は他の場所でも受け入れられた答えを証拠として見ました。ただし、簡単に理解できますが、間違っています。それが証明しているのは

x=z

あなたが本当に証明したいのは、上記の受け入れられた答えの図で説明されているのと同じ変数を使用することです:

z=x mod (y+z)

(y+z)L

だから、私たちが証明したいのは:

z=x mod L

または、zがx(モジュロL)と一致していること

次の証明は私にとってより理にかなっています:

M=x+y

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

x+y=kL

x=kLy

The above equation proves that x is the same as some multiple of loop length, L minus y. So, if the fast pointer starts at the meeting point, M or at x+y, then it will end up at the start of the loop.


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.