カメとウサギのアルゴリズムを使用したサイクル検出のウィキペディアの実装を行っていました。Ruby言語を使用して、これが私が実装したものです:
def tortoise_and_hare(シーケンス)
亀 = 1
うさぎ= 2
while シーケンス[亀] != シーケンス[ウサギ]
カメ += 1
うさぎ += 2
終わり
# 最初の繰り返しの開始インデックスを見つける
idx = 0
亀 = 0
while シーケンス[亀] != シーケンス[ウサギ]
カメ += 1
うさぎ += 1
idx += 1
終わり
# インデックス idx から始まるサイクルの長さを見つける
長さ = 1
ウサギ=カメ+1
while シーケンス[亀] != シーケンス[ウサギ]
うさぎ += 1
長さ += 1
終わり
[idx、長さ]
終わり
シーケンス = [2, 0, 6, 3, 1, 6, 3, 1, 6, 3, 1]
idx、長さ = tortoise_and_hare(sequence)
pシーケンス[idx、長さ]
これは正しく機能しており、[6, 3, 1]. 今、
- シーケンスを にトリミングすると
[2, 0, 6, 3, 1, 6, 3, 1]、空のセットが返されます。 - 問題は 2 番目のループにあることがわかります。サイクルに繰り返し文字がある場合、アルゴリズムは間違った答えを返します。例、 を
[2, 0, 6, 3, 1, 6, 6, 3, 1, 6, 6, 3, 1, 6]返しますが[6, 3, 1]、 である必要があります[6, 3, 1, 6]。問題は 3 番目のループにあることがわかります。
だから私は私の質問は次のとおりだと思います:
- アルゴリズムはウィキペディア標準に掲載されていますか?
- 私の2番目のケースは間違っていますか? サイクル検出とは、私の試験ではない非常に長いシーケンスを意味することを知っていますが、それでもサイクルがあります。
- ケースが正しければ、アルゴリズムを改善し、上記で指摘した 2 つの問題を解決するにはどうすればよいでしょうか?
最初の問題の2番目のループを変更しようとしました(アルゴリズムが失敗するのに十分なほど小さいシーケンスをトリミングしました)が、うまくいきました:
# 最初の繰り返しの開始インデックスを見つける
idx = 0
亀 = 0
while シーケンス[亀] != シーケンス[ウサギ]
カメ += 1
うさぎ += 1
ウサギ > sequence.length - 1 の場合、ウサギ = カメ
idx += 1
終わり
- 間違っているように見えますか、場合によっては失敗する可能性がありますか?
- 2番目の問題(文字の繰り返し)に対して何ができますか?
別のエレガントな正規表現ベースのソリューションを思いつきましたが、上記のアルゴリズムについてもっと知りたいと思っています。
好奇心のための正規表現ソリューション:/(?<cycle>(\d+\s)+(\d+))\s\k<cycle>/
編集:繰り返し文字を検出できない理由がわかりました。しかし、この状況で役立つ可能性のある他のアルゴリズムはありますか?