サイクルが非常に少ない場合は、使用するスペースは少なくなりますが、終了するまでにかなり時間がかかるアルゴリズムを次に示します。
[編集]私の以前のランタイム分析では、訪問するノードが以前にサンプリングされたノードの中にあるかどうかを判断するための重要なコストを逃しました。この回答はこれを修正するために多少修正されています。
Sのすべての要素を繰り返します。我々は要素の軌道探求としての ∈ Sを、我々は再び彼らに遭遇しているかどうかを確認することができるようにするために、私たちが訪問したことのノードからのサンプル。また、以前にアクセスした「コンポーネント」(共通のサイクルで終了する(したがって、サイクルと等しい)軌道の和集合)のサンプルのリストも維持します。
コンポーネントの空のリストを初期化しますcomplist
。各コンポーネントは、そのコンポーネントのサンプルのコレクションによって表されます。また、samples
コンポーネントなどのサンプルとして選択されたすべての要素を格納する検索ツリーも維持します。LET Gは最大の整数のシーケンスであるn個のメンバーシップは、いくつかのブール述語を計算することによって効率的に決定されています; 例えば、2つのまたは完璧なのべき乗のp 番目のいくつかの整数のための力のp。それぞれについて、S ∈ S、次の操作を行います。
- sがにある場合は、
samples
手順5に進みます。
- 空のリスト
cursample
、イテレーターj ←f(s)、およびカウンターt ←1を初期化します。
- 一方でjはしていない
samples
:
-もしT ∈ G、挿入jの両方にcursample
とsamples
。
— tをインクリメントし、j ← f(j)を設定します。
- jが内にあるかどうかを確認してください
cursample
。そうでない場合は、以前に調査したコンポーネントに遭遇しました。jが属するコンポーネントを確認し、のすべての要素cursample
をの適切な要素に挿入して、complist
それを拡張します。それ以外の場合は、現在の軌道から要素に再遭遇しました。つまり、以前に発見されたサイクルの代表に遭遇することなく、少なくとも1回サイクルをたどったことを意味cursample
しcomplist
ます。新しく見つかったコンポーネントからのサンプルのコレクションとして、をに挿入します。
- 次の要素に進んでS ∈ S。
以下のためのn = | S |、X(n)を期待されるサイクル数を表す単調増加関数(たとえば X(n) = n 1/3)とし、Y(n) = y(n) log(n)∈Ω(X(n) log(n))は、メモリ使用量のターゲットを決定する単調増加関数です(たとえば、 y(n) = n 1/2)。我々は必要とY(N) ∈Ω(X(N) )が少なくとも取るためX(n)は、 ログ(nは各コンポーネントからの1個のサンプルを格納するために)スペースを。
サンプリングする軌道の要素が多いほど、軌道の終わりのサイクルでサンプルをすばやく選択して、そのサイクルをすばやく検出する可能性が高くなります。漸近的な観点からは、メモリの境界が許す限り多くのサンプルを取得することは理にかなっています。Gがnより小さい期待されるy(n)要素を持つように設定することもできます。— Sの軌道の最大長がLであると予想される場合、GをL / y(n)の整数倍にすることができます。—予想される長さが存在しない場合、n / y(n)ごとに1回サンプリングするだけです。
要素; これはいずれにしても、サンプル間の間隔の上限です。
新しいコンポーネントを探す際に、以前にアクセスしたSの要素をトラバースし始める場合(新しいコンポーネントが発見されているか、またはターミナルサイクルが既に見つかっている古いコンポーネントから)、最大でn / y( n)以前にサンプリングされた要素に遭遇するための反復。これは、回数の上限です。新しいコンポーネントを見つけるたびに、冗長ノードをたどります。このような試みをn回行うので、Sの要素を合計で最大n 2 / y(n)回冗長に訪問します。
のメンバーシップをテストするために必要な作業samples
はO(y(n) log y(n))であり、これは訪問ごとに繰り返されます。このチェックの累積コストはO(n 2 log y(n))です。また、サンプルをそれぞれのコレクションに追加するコストもあり、累積的にO(y(n) log y(n))になります。最後に、以前に発見されたコンポーネントに再遭遇するたびに、最大X(n) log * y(n)の時間を費やして、どのコンポーネントを再発見したかを判別する必要があります。これはn回まで発生する可能性があるため、関連する累積作業はn X(n) log y(n)によって制限されます 。
したがって、アクセスするノードがサンプルの中にあるかどうかをチェックする際に実行される累積的な作業がランタイムを支配します。これにはO(n 2 log y(n))がかかります 。次に、y(n)をできるだけ小さくする必要があります。つまり、O(X(n))です。
したがって、O(n(2) log X(n))を取って、O(X(n) log(n))空間でサイクル数(これらのサイクルで終了するコンポーネントの数と同じ)を列挙できます。そうする時間が、ここでX(n)は、サイクルの予想される数です。