亀と野ウサギの会議はループの存在を終了することを理解していますが、ウサギを会議場所に置いたまま、リンクされたリストの先頭に亀を移動し、次に両方を1ステップずつ移動して、サイクルの開始点で会うにはどうすればよいですか?
亀と野ウサギの会議はループの存在を終了することを理解していますが、ウサギを会議場所に置いたまま、リンクされたリストの先頭に亀を移動し、次に両方を1ステップずつ移動して、サイクルの開始点で会うにはどうすればよいですか?
回答:
これは、サイクル検出用のフロイドのアルゴリズムです。アルゴリズムの第2フェーズについて質問しています。サイクルの一部であるノードを見つけたら、どのようにしてサイクルの開始を見つけるのでしょうか。
フロイドのアルゴリズムの最初の部分では、ウサギはカメのすべてのステップで2ステップ移動します。亀とうさぎが出会う場合は、循環があり、その集合点は循環の一部ですが、必ずしも循環の最初のノードではありません。
カメとウサギが出会ったとき、X i = X 2iとなるような最小のi(カメの歩数)を見つけました。muがX 0からサイクルの開始までのステップ数を表し、lambdaがサイクルの長さを表すとします。次に、i = mu + a ラムダ、2i = mu + bラムダです。ここで、aとbは、亀とウサギがサイクルを何回行ったかを表す整数です。2番目の方程式から最初の方程式を引くと、i =(ba)* lambdaとなるため、iはラムダの整数倍になります。 したがって、X i + mu = X muです。X iは、カメとウサギの出会いの場を表します。亀を最初のノードXに戻した場合0、そして亀とウサギが同じ速度で継続するようにします。mu追加のステップの後、亀はX muに到達し、ウサギはX i + mu = X muに到達します。したがって、2番目のミーティングポイントは、サイクル。
X_mu
、サイクルの開始(muの定義による)に到達します。次に、iをさらにステップ実行すると、iはサイクルの長さの倍数であり、最終的にサイクルの開始点に戻ります:X_mu + i
= X_mu
。しかし、加算は可換的であるため、これは、最初から最初のミーティングポイントに到達するためにiステップを実行しX_i
、次にX_mu
、サイクルの開始に戻るためにmu追加ステップを実行することと同じです。
i
はサイクルのある時点にあるので、方程式はi = mu + k + a*lambda
and 2i = mu + k + b*lambda
である必要があると思います。ここで、k
はサイクルの開始から待ち合わせポイントまでのステップ数です。ただし、両方の方程式を引くと同じ結果になります。
自分の言葉でhttp://en.wikipedia.org/wiki/Cycle_detection#Tortoise_and_hareで提供されているサイクル検出アルゴリズムを明確にしてみましょう。
使い方
上の図のように、リストの先頭をサイクルで指している亀とウサギ(ポインタの名前)を見てみましょう。
亀を一度に1歩ずつ動かし、一度に2歩歩くと、ある時点で最終的に出会うと仮定しましょう。まず、この仮説が真であることを示しましょう。
この図は、循環のあるリストを示しています。サイクルの長さはn
、最初m
はサイクルから離れています。また、出会いのポイントはk
、サイクルの開始から少し離れたところにあり、亀がi
完全な一歩を踏み出したときに亀とウサギが出会うとします。(ヘアはそれまでに2i
完全なステップを踏んでいたでしょう。)
次の2つの条件が満たされている必要があります。
1) i = m + p * n + k
2) 2i = m + q * n + k
最初のものは、亀がi
ステップを動かし、これらのi
ステップで最初にサイクルに入ると言います。次に、p
正の数のサイクルタイムを通過しますp
。最後に、k
ウサギに出会うまで、より多くのノードを調べます。
ウサギについても同様です。2i
ステップを移動し、これらの2i
ステップで最初にサイクルに到達します。次に、q
正の数のサイクルタイムを通過しますq
。最後に、k
亀に出会うまで、より多くのノードを通過します。
ウサギは亀の2倍の速度で移動するため、出会い地点に到達するまでの時間はどちらも一定です。
簡単な速度、時間、距離の関係を使用して、
2 ( m + p * n + k ) = m + q * n + k
=> 2m + 2pn + 2k = m + nq + k
=> m + k = ( q - 2p ) n
m、n、k、p、qのうち、最初の2つは指定されたリストのプロパティです。この方程式を真にするk、q、pの値のセットが少なくとも1つあることを示すことができれば、仮説が正しいことを示します。
そのようなソリューションセットの1つは次のとおりです。
p = 0
q = m
k = m n - m
これらの値が次のように機能することを確認できます。
m + k = ( q - 2p ) n
=> m + mn - m = ( m - 2*0) n
=> mn = mn.
このセットのために、i
あります
i = m + p n + k
=> m + 0 * n + mn - m = mn.
もちろん、これが必ずしも最小のiであるとは限らないことがわかります。つまり、亀とうさぎは何度も会ったことがあるかもしれません。しかし、少なくとも一度はそれらがどこかで出会うことを示しているので、仮説は正しいと言えます。したがって、それらの1つを1ステップずつ動かし、他の1つを2ステップずつ動かす場合、それらは一致する必要があります。
これで、アルゴリズムの2番目の部分であるサイクルの始まりを見つける方法に進むことができます。
サイクルの始まり
亀とうさぎが出会ったら、亀をリストの最初に戻し、出会った場所にうさぎを留めましょう(サイクルの開始からkステップ離れています)。
仮説は、彼らが同じ速度(両方とも1ステップ)で動くようにすると、彼らが再び会うのは初めてのときがサイクルの始まりになるということです。
この仮説を証明しましょう。
最初に、いくつかのオラクルがmが何であるかを教えてくれると仮定しましょう。
次に、m + kステップ移動させると、亀は最初に出会った地点に到着する必要があります(サイクルの開始からkステップ-図を参照)。
以前はそれを示しましたm + k = (q - 2p) n
。
m + kステップはサイクル長nの倍数であるため、うさぎは、平均すると、サイクル(q-2p)回を通過し、同じポイントに戻ります(サイクル開始からkステップ離れます)。
ここで、m + kステップだけ移動させるのではなく、mステップだけ移動させると、亀がサイクルの開始点に到達します。うさぎは(q-2p)回転を完了するのにkステップ足りません。サイクルの開始前にkステップ開始したため、ウサギはサイクルの開始に到達する必要があります。
その結果、これは、最初にいくつかのステップの後に始まるサイクルで初めて会う必要があることを説明します(亀はmステップ後にサイクルに到着したばかりで、すでに入っているウサギを見ることができなかったため、初めて)サイクル)。
これで、それらが出会うまでそれらを移動するために必要なステップの数は、リストの最初からサイクルの始まりmまでの距離であることがわかりました。もちろん、アルゴリズムはmが何であるかを知る必要はありません。カメを動かし、出会うまで一度に1歩ずつウサギを動かします。待ち合わせポイントはサイクルの開始点である必要があり、ステップ数はサイクルの開始点までの距離(m)でなければなりません。リストの長さがわかっていれば、リストの長さからmを引くサイクルの長さを計算することもできます。
m + k = (q - 2p) n
はさらにに簡略化できますm + k = q*n
。これは、ウサギが亀に会わずに追い抜くことはできないため、亀が取るループの数は常にゼロになるためです。それについて考えてください。
この画像を参照してください:
会議前にslowPointerが移動した距離 = x + y
会議前にfastPointerが移動した距離 =(x + y + z)+ y = x + 2y + z
fastPointerはslowPointerの2倍の速度で移動するため、がミーティングポイントに到達するまでの時間はどちらも一定です。
したがって、単純な速度、時間、距離の関係を使用して2(x + y)= x + 2y + z => x + 2y + z = 2x + 2y => x = z
したがって、slowPointerをリンクリストの先頭に移動し、slowPointerとfastPointerの両方が一度に1つのノードを移動するようにすると、どちらも同じ距離でをカバーできます。
それらは、リンクされたリストでループが開始するポイントに到達します。
Old Monkのシンプルで賛成されていない答えは、高速ランナーが単一の完全なサイクルのみを完了したときにサイクルを見つけることを説明しています。この回答では、遅いランナーがループに入る前に、速いランナーがループを複数回実行した場合について説明します。
高速ランナーが低速と高速の出会いの前にループをm回実行したとします。この意味は:
fastはslowの2倍の速度で実行され、同時に実行されているため、slowが実行した距離を2倍にすると、fastが実行した距離が得られます。したがって、
xを解くと、
x =(m-1)(y + z)+ z
実際のシナリオでは、x = (m-1)完全なループの実行+追加の距離zを意味します。
したがって、リストの最初に1つのポインターを置き、もう1つのポインターをミーティングポイントに置いたままにすると、それらを同じ速度で移動すると、ループ内ポインターがループのm-1回の実行を完了し、もう1つのループを満たします。ループの先頭にあるポインター。
最初の衝突時に、亀は上記のようにm + kステップ移動しました。うさぎは亀の2倍の速度で移動します。つまり、うさぎは2(m + k)ステップ移動します。これらの単純な事実から、次のグラフを導き出すことができます。
この時点で、亀を最初に戻し、ウサギと亀の両方が一度に1ステップずつ移動する必要があることを宣言します。定義により、mステップ後、亀はサイクルの開始点になります。野ウサギはどこにいますか?
うさぎもまた、サイクルの初めにいます。これは2番目のグラフから明らかです。亀が最初に戻ったとき、ウサギは最後のサイクルにk歩進みました。mステップ後、ウサギは別のサイクルを完了し、亀と衝突します。
アプローチ:
2つのポインタがあります。
2つのポインターが出会った場合は、ループがあることを証明しています。それらが出会うと、ノードの1つがヘッドをポイントし、両方が一度に1つのノードを処理します。彼らはループの開始時に会います。
理論的根拠: 2人が円形のトラックを歩くとき、2人がもう1人の2倍の速度で歩いている場合、どこで出会いますか?まさに彼らが始まったところ。
ここで、ファストランナーがステップラップでk
ステップの先頭に立っているとしますn
。彼らはどこで会いますか?まさにn-k
ステップで。スローランナーが(n-k)
ステップをカバーした場合、ファーストランナーがk+2(n-k)
ステップをカバーしたことになります。(すなわち、k+2n-2k
ステップすなわち2n-k
ステップ)。つまり、(n-k)
ステップ数(パスは円形であり、それらが出会うまでのラウンド数は関係ありません。出会う位置だけに関心があります)。
さて、ファーストランナーはそもそもどのようにしk
て最初のステップを開始したのでしょうか。ループの開始に到達するまでに多くのステップを実行するのに時間がかかるためです。したがって、ループの開始はヘッドノードからkステップです。
注:両方のポインターが出会ったノードはk
、ループの開始(ループ内)k
から少し離れており、ヘッドノードもループの開始から少し離れています。したがって、これらのノードをボットから1ステップの等速で前進するポインターがある場合、それらはループの開始時に出会います。
簡単だと思います。不明な部分がありましたらお知らせください。
さて、サイクルの開始からkステップ離れたポイントでウサギとカメが出会うと仮定しましょう。サイクルが開始するまでのステップ数はmuで、サイクルの長さはLです。
だから今、待ち合わせ場所->
亀で覆われた距離= mu + a * L + k-式1
(サイクルの最初に到達するために取られるステップ+サイクルの「a」回の反復をカバーするために取られるステップ+サイクルの開始からkステップ)(ここで、aは正の定数です)
野ウサギがカバーする距離= mu + b * L + k-式2
(サイクルの最初に到達するために取られるステップ+サイクルの「b」回の反復をカバーするために取られるステップ+サイクルの開始からkステップ)(bはいくつかの正の定数であり、b> = a)
したがって、ウサギがカバーする追加の距離は=方程式2-方程式1 =(ba)* L
ノウサギはカメより2倍速く移動するため、この距離は開始点からのカメの距離にも等しいことに注意してください。これは 'mu + k'と同等である可能性があります。これは、サイクルの複数のトラバーサルを含めない場合の、最初からのミーティングポイントの距離でもあります。
したがって、mu + k =(ba)* L
したがって、このポイントからのmuステップは、サイクルの最初に戻ります(サイクルの開始からkステップは、ミーティングポイントに到達するためにすでに取得されているため)。これは、同じサイクルまたは後続のサイクルのいずれかで発生する可能性があります。したがって、リンク先のリストの先頭に亀を移動すると、サイクルの開始点に到達するまでにmuのステップが必要になり、ウサギがサイクルの開始点に到達するまでにmuのステップが実行されます。サイクルの開始点。
PS正直なところ、私は元のポスターと同じ質問を心に抱き、最初の回答を読みました。彼らはいくつかのことをクリアしましたが、最終結果を明確に得ることができなかったので、私は自分の方法でそれを試みました理解しやすかった。
ポインターがたどるリンクの数と、低速ポインターを1つのリンクに、高速ポインターを2つのリンクに移動するためにアルゴリズムが実行する反復回数に時間をかけます。長さCのサイクルの前にN個のノードがあり、サイクルオフセットk = 0からC-1までのラベルが付けられています。
サイクルの開始に到達するには、スローにはN時間と距離がかかります。これは、サイクルでNの距離が高速にかかることを意味します(Nはそこに到達し、Nはスピンします)。したがって、時間Nでは、低速はサイクルオフセットk = 0にあり、高速はサイクルオフセットk = N mod Cにあります。
N mod Cがゼロの場合、低速と高速が一致し、サイクルは時間Nでサイクル位置k = 0で検出されます。
N mod Cがゼロでない場合、fastはslowに追いつく必要があります。このとき、NはサイクルのC-(N mod C)の距離の遅れです。
fastは、slowの1ごとに2を移動し、反復ごとに距離を1ずつ減らすため、これには、Nでのfastとslowの間の距離(C-(N mod C))と同じだけ多くの時間がかかります。slowはオフセット0から移動しているため、これらが出会うオフセットでもあります。
そのため、N mod Cがゼロの場合、フェーズ1はサイクルの開始時にN回の反復後に停止します。それ以外の場合、フェーズ1は、サイクルへのオフセットC-(N mod C)でのN + C-(N mod C)の反復後に停止します。
// C++ pseudocode, end() is one after last element.
int t = 0;
T *fast = begin();
T *slow = begin();
if (fast == end()) return [N=0,C=0];
for (;;) {
t += 1;
fast = next(fast);
if (fast == end()) return [N=(2*t-1),C=0];
fast = next(fast);
if (fast == end()) return [N=(2*t),C=0];
slow = next(slow);
if (*fast == *slow) break;
}
わかりましたので、フェーズ2:スローはサイクルに到達するまでにさらにNステップを要します。この時点で、ファスト(タイムステップごとに1つ移動)は(C-(N mod C)+ N)mod C = 0になります。フェーズ2の後のサイクルの開始時。
int N = 0;
slow = begin();
for (;;) {
if (*fast == *slow) break;
fast = next(fast);
slow = next(slow);
N += 1;
}
完全を期すために、フェーズ3はサイクルをもう一度移動することによってサイクルの長さを計算します。
int C = 0;
for (;;) {
fast = next(fast);
C += 1;
if (fast == slow) break;
}
問題をループ問題に減らしてから、最初の問題に戻ります
次の説明の方が直感的です。
(二つのポインタを取る1 =亀と2頭(から始まる=ウサギ)Oが)、1のステップ長持つ1、2のステップ長持つ2。1がそのサイクルの開始ノード(A)に到達した瞬間を考えてみてください。
次の質問に答えたいと思います。。
つまり、OA = a
は自然数(a >= 0
)です。しかし、それは次のように書くことができます:a = k*n + b
ここでa, k, n, b are natural numbers
:
n
=サイクルの長さk >= 0
=一定0 <= b <= n-1
ということb = a % n
です。
例:if a = 20
およびn = 8
=> k = 2
およびb = 4
because 20 = 2*8 + 4
。
1でカバーされる距離はd = OA = a = k*n + b
です。しかし同時に、2がカバーしD = 2*d = d + d = OA + d = OA + k*n + b
ます。これは、2がAの場合、カバーする必要があることを意味しますk*n + b
。あなたが見ることができるように、k
ラップの数があるが、これらのラップの後、2になりますbはどこ遠くA.そうから、我々が発見2がときである1が A.レッツ・コール、その点でありB
、AB = b
。
今、私たちは問題を円に減らします。問題は、「待ち合わせ場所はどこですか」です。。そのCはどこですか
すべてのステップでは、2からの距離が減少し1で1
あるため(LETの言うメーター)1からさらになっている2と1
が、同時に2が近づくに行く1によります2
。
したがって、交差は1と2の間の距離がゼロになるときになります。つまり、2はn - b
距離を短くします。これを達成するために、1はn - b
ステップを実行し、2は2*(n - b)
ステップを実行します。
したがって、交点n - b
はA(時計回り)から遠くなります。これは、2に出会うまで1でカバーされる距離だからです。=>との間の距離CとAがであり、なぜなら、および。それを考えてはいけないので、距離は些細な数学的な距離ではありません、それは間のステップ数で、AとC(Aは、開始点であるとCは、エンドポイントです)。CA = b
AC = AB + BC = n - b
CA = n - AC
AC = CA
AC
では、最初のスキーマに戻りましょう。
我々はそれを知っているa = k*n + b
とCA = b
。
私たちは、2つの新しいポインタ取ることができます1'及び1 『』を、どこ1'頭(から始まりO)および1 『』交点(から始まるC)。
一方で1'から行くOにA、『1』から行くCにAとフィニッシュまで続くk
ラップ。したがって、交点はAです。
図に示すようにポインタが点Pで出会った場合、距離Z + Yは点Pであり、X + Yも点Pであり、これはZ = Xを意味します。これが、あるポインタをPから移動し、別のポインタをstart(S)からそれらが出会うまで移動し続ける理由です。つまり、等しい距離(ZまたはX)を同じ点M(Pからの距離ZおよびSからの距離)に移動すると、ループの開始。シンプル!
上記のすべての分析で、例で学習する人であれば、他の誰もが説明しようとした数学を説明するのに役立つ短い分析と例を書いてみました。さあ行こう!
分析:
2つのポインターがあり、一方が他方よりも速く、一緒に移動する場合、それらは最終的に再び会合してサイクルを示すか、nullでサイクルがないことを示します。
サイクルの開始点を見つけるには、...
m
頭からサイクルの開始までの距離。
d
サイクル内のノード数。
p1
遅いポインタの速度です。
p2
より速いポインタの速度である、例えば。2は、一度に2つのノードをステップ実行することを意味します。
次の反復を観察します。
m = 0, d = 10: p1 = 1: 0 1 2 3 4 5 6 7 8 9 10 // 0 would the start of the cycle p2 = 2: 0 2 4 6 8 10 12 14 16 18 20 m = 1, d = 10: p1 = 1: -1 0 1 2 3 4 5 6 7 8 9 p2 = 2: -1 1 3 5 7 9 11 13 15 17 19 m = 2, d = 10: p1 = 1: -2 -1 0 1 2 3 4 5 6 7 8 p2 = 2: -2 0 2 4 6 8 10 12 14 16 18
上記のサンプルデータから、速いポインターと遅いポインターが出会うときはいつでも、それらはm
サイクルの開始から一歩離れていることが簡単にわかります。これを解決するには、速いポインターを先頭に戻し、その速度を遅いポインターの速度に設定します。彼らが再び会うとき、ノードはサイクルの始まりです。
まあ言ってみれば、
N[0] is the node of start of the loop,
m is the number of steps from beginning to N[0].
2つのポインターAとBがあります。Aは1倍速で実行され、Bは2倍速で実行されます。どちらも最初から開始されます。
AがN [0]に達したとき、BはすでにN [m]にあるはずです。(注:AはN [0]に到達するためにmステップを使用し、Bはさらにmステップでなければなりません)
次に、Aはさらにkステップ実行してBに衝突します。つまり、AはN [k]にあり、BはN [m + 2k]にあります(注:BはN [m]から2kステップ実行する必要があります)
AはそれぞれN [k]とN [m + 2k]で衝突します。これはk = m + 2kを意味するため、k = -m
したがって、N [k]からN [0]にサイクルバックするには、さらにmステップが必要です。
簡単に言うと、衝突ノードが見つかった後、さらにmステップ実行する必要があります。最初から実行するポインタと衝突ノードから実行するポインタを設定できます。これらは、mステップ後にN [0]で交わります。
したがって、擬似コードは次のとおりです。
1) A increase 1 step per loop
2) B increase 2 steps per loop
3) if A & B are the same node, cycle found, then go to 5
4) repeat from 1
5) A reset to head
6) A increase 1 step per loop
7) B increase 1 step per loop
8) if A & B are the same node, start of the cycle found
9) repeat from 6
彼らが出会ったときにそれが出発点であるというのは本当ではないと思います。しかし、他のポインター(F)がの前のミーティングポイントにあった場合、そのポインターはループの開始ではなく、ループの最後にあり、リストの開始から開始したポインター(S)は、ループの開始時に終了します。たとえば:
1->2->3->4->5->6->7->8->9->10->11->12->13->14->15->16->17->18->19->20->21->22->23->24->8
Meet at :16
Start at :8
public Node meetNodeInLoop(){
Node fast=head;
Node slow=head;
fast=fast.next.next;
slow=slow.next;
while(fast!=slow){
fast=fast.next;
fast=fast.next;
if(fast==slow) break;
slow=slow.next;
}
return fast;
}
public Node startOfLoop(Node meet){
Node slow=head;
Node fast=meet;
while(slow!=fast){
fast=fast.next;
if(slow==fast.next) break;
slow=slow.next;
}
return slow;
}
高校で教えられた相対速度の概念を使用した簡単な説明-物理学101 /運動学の講義。
リンクされたリストの開始からサークルの開始までの距離がx
ホップであると仮定しましょう。円の始点をポイントと呼びましょうX
(大文字で-上図を参照)。また、円の合計サイズがNホップであると仮定します。
ノウサギの速度= 2 *カメの速度。つまり1 hops/sec
、2 hops/sec
それぞれ
亀が円の始点に到達するX
と、ノウサギは図のx
ポイントY
でさらにホップを離れる必要があります。(ウサギが亀の2倍の距離を移動したため)。
したがって、XからYへの時計回りの残りの弧の長さはになりますN-x
。これは、うさぎとカメが出会うために必要な相対距離でもあります。この相対距離がt_m
時間内に満たされる、つまり、会う時間になるとしましょう。相対速度がある(2 hops/sec - 1 hops/sec)
すなわち1 hops/sec
。したがって、相対距離=相対速度X時間を使用すると、t
= N-x
秒になります。したがってN-x
、カメとウサギの両方の待ち合わせ場所に到達するまでに時間がかかります。
今ではN-x
秒の時間とで1 hops/sec
スピード、早い時点でいた亀X
のNxをカバーするには、ミーティングポイントに到達するためにホップM
。つまり、ミーティングポイントM
は、(さらに意味する)=> N-x
から反時計回りのホップにX
ありx
、ポイントM
からX
時計回りまでの距離が残っていることを意味します。
しかし、リンクされたリストの最初からx
到達点X
までの距離でもあります。
ここで、ホップ数が何であるかは関係ありませんx
。LinkedListの先頭に1匹のカメを置き、ミーティングポイントに1匹のカメを置いM
てホップ/ウォークさせるX
と、必要なポイント(またはノード)であるポイントで合体します。
これを図で操作すると役立ちます。方程式なしで問題を説明しようとしています。
-ループの前にkステップあります。私たちはkが何であるかを知りませんし、知る必要もありません。kだけで抽象的に作業できます。
-kステップ後
----- Tはサイクル開始時
----- Hはサイクルへのkステップです(彼は合計で2kになり、したがってループにk入りました)
**それらはループサイズになりました-k離れています
(k == K == mod(loopsize、k)であることに注意してください。たとえば、ノードが5ノードサイクルに2ステップある場合、7、12、または392ステップもあるので、サイクルの大きさはkではありません。要因で。
一方が他方の2倍の速度で移動しているため、単位時間あたり1ステップの速度で互いに追いつくため、loopsize-kで出会います。
これは、サイクルの開始点に到達するためにk個のノードを必要とすることを意味し、したがって、ヘッドからサイクルスタートまでの距離と衝突からサイクルスタートまでの距離は同じです。
したがって、最初の衝突の後、Tを頭に戻します。TとHは、それぞれ1のレートで移動する場合、サイクルスタートで出会います。(両方でkステップ)
つまり、アルゴリズムは次のとおりです。
//ループの長さを計算して、k = 0、またはTとHがループの先頭で出会った場合に対応
-カウンターでTまたはHを移動してサイクルの長さをカウントします。
-ポインタT2をリストの先頭に移動します
-サイクルステップのポインタ長を移動します。
-別のポインタH2を先頭に移動します。
-サイクルの開始時に出会うまで、T2とH2をタンデムに移動します
それでおしまい!
この問題についてはすでに認められた回答があることは知っていますが、それでも流動的な方法で回答するように努めます。想定:
The length of the Path is 'X+B' where 'B' is the length of the looped path and X of the non looped path.
Speed of tortoise : v
Speed of hare : 2*v
Point where both meet is at a distance 'x + b - k' from the starting point.
さて、ウサギとカメは最初から「t」後に会いましょう。
観察:
もし、カメが移動した距離= v * t = x +(bk)(たとえば)
次に、うさぎが移動した距離= 2 * v * t = x +(b-k)+ b(うさぎがループした部分をすでに通過したため)
現在、会議の時間は同じです。
=> x + 2 * b-k = 2 *(x + b-k)
=> x = k
もちろん、これは、ループされていないパスの長さが、両方が交わるポイントからループの開始ポイントまでの距離と同じであることを意味します。
出会い系の背後にある数学を考えると、両方が開始点で出会うことを証明するのは実際には簡単です。
まず、mはリンクリストのサイクルの開始点を示し、nはサイクルの長さを示します。次に、ノウサギとカメに会うために、
( 2*t - m )%n = (t - m) %n, where t = time (at t = 0 , both are at the start)
これをより数学的に述べる:
(2*t - m - (t - m) ) = 0 modulo n , which implies , t = 0 modulo n
そのため、それらはサイクルtの倍数であるはずの時間tで出会います。これは、彼らがである場所で会うことを意味し
(t-m) modulo n = (0-m) modulo n = (-m) modulo n
ます。
したがって、質問に戻って、リンクリストの先頭から1つのポインタを移動し、交点から別のポインタを移動すると、mステップ後に、ウサギ(サイクル内で移動している)が((-m) + m) modulo n = 0 modulo n
これは、サイクルの開始点にすぎません 。リンクされたリストの先頭からmステップ移動するので、mステップ後にサイクルの開始となり、亀がそこでそれに出会うことがわかります。
条件は:サイドノートとして、我々はまた、このように自分の交差点の時間を計算することができt = 0 modulo n
、彼らはサイクル長の倍数である時に会うことを教えてくれるし、またtはより大きくなければなりませメートル彼らが会うようサイクル。したがって、かかる時間は、mより大きいnの最初の倍数に等しくなります。
ポインターが点yとzの交点で交わるとします。
nとmは、会議の前にそれぞれポインタが取るループと速いループの数です。
残りの証明については、画像を参照してください。 リンクされたリストでループの開始点を見つける