あなたが持っているときは、本当に大きなファイルや多くのそれの要素を、最も一般的な要素が非常に一般的である-起こる時間の割合を-あなたは宇宙との線形時間でそれを見つけることができますO (K )(言葉O ()表記の定数は非常に小さく、ハッシュなどの補助的なもののストレージをカウントしない場合は基本的に2です)。さらに、ファイルは一度に1つの要素で順番に処理され、アルゴリズムは決して「振り返る」ことはないため、これは外部ストレージでうまく機能します。これを行う1つの方法は、MisraとGriesによる古典的なアルゴリズムを使用することです。これらの講義ノートを参照してください>1/kO(k)O()。この問題は現在、ヘビーヒッターの問題として知られています(頻繁な要素はヘビーヒッターです)。
前提最も頻繁要素が表示されていることための時間の割合kの小さな数は強いように見えるかもしれませんが、それは必要な方法であります!つまり、ファイルへのシーケンシャルアクセスがある場合(およびファイルが巨大なランダムアクセスの場合は高額になります)、一定のパス数で最も頻繁な要素を常に見つけるアルゴリズムは、要素数に線形のスペースを使用します。したがって、入力について何かを仮定しないと、ハッシュテーブルに勝てません。最も頻繁な要素が非常に頻繁であるという仮定は、おそらく否定的な結果を回避する最も自然な方法です。>1/kk
以下はスケッチです。つまり、半分以上の時間で発生する単一の要素がある場合です。この特別なケースは多数決アルゴリズムとして知られており、ボイヤーとムーアによるものです。単一の要素と単一のカウントを保持します。カウントを1に初期化し、ファイルの最初の要素を保存します。次に、ファイルを順番に処理します。k=2
- ファイルの現在の要素が保存されている要素と同じである場合、カウントを1つ増やします
- ファイルの現在の要素が保存されている要素と異なる場合は、カウントを1つ減らします
- 更新されたカウントが0の場合、保存されている要素を「追い出し」、ファイルの現在の要素を保存します。カウントを1に増やします
- ファイルの次の要素に進みます
この手順について少し考えてみると、「多数」要素、つまり半分以上の時間で発生する要素が存在する場合、その要素はファイル全体が処理された後の保存された要素になります。
一般の場合、あなたは保つのk - 1つの要素とK - 1つのカウントを、あなたが最初に初期化する要素kのあなたが見る前に、これらの各要素が表示された回数にファイルの異なる要素とカウントをK番目別個の要素。その後、基本的に同じ手順を実行します。検出されるたびに要素のカウントが増加し、保存されていない要素が検出されるとすべての要素カウントが減少し、カウントがゼロの場合、その要素が追い出されますファイルの現在の要素。これはMisra-Griesアルゴリズムです。kk−1k−1kk
もちろん、ハッシュテーブルを使用して、保存された要素にインデックスを付けることができます。終了時に、このアルゴリズムは、時間の1 / kを超える割合で発生する要素を返すことが保証されています。これは、ファイル上で一定数のパスを作成し、O (k )ワードのみを保存するアルゴリズムを使用して実行できる最善の方法です。k−11/kO(k)
k1/kk−1