重複のない最大で1千万の7桁の整数を含むファイルがあるとします。 1.5MB RAMを使用してデータを1回だけ読み取ることでこれらの数値を昇順で印刷する効率的な方法は何ですか?重複が許可されている場合はどうなりますか?
私はグーグルで上記の質問に出くわしましたが、関連する答えは見つかりません。グーグルリサーチ/回答と私の理解に基づいて、私はこれがアプローチとアルゴリズムであると信じています(言語をJavaと見なしますが、ほとんどのポイントでは重要ではありません)。各ポイントに対する特定のクエリ
Javaでは、整数は4バイト整数であると想定しています。ここでは長さ(7桁や6桁など)は重要ではないと思いますか?
1.5 MB ram = 1.5/4 = 375k(4は4バイトの整数を表す)に対応できる整数の数は、0.3百万の整数になります。つまり、0.3 MBの整数を1.5 MBのメモリの下で一度に並べ替えることができます。
メモリ内の最初の300万の整数を並べ替えて、一時ファイルに書き込みます。
.300万の別のロットを選択し、これを手順3で作成した一時ファイルとマージして、新しい一時ファイルを作成します。手順3で削除します。
プロセスが完了するまで、つまり10/.3 = 34回、手順4を繰り返します。
このアルゴリズムは正しいですか?はいの場合、重複を許可すると、ここにどのような影響がありますか?
ビットフィールドを使用できると思います。つまり、0〜9,999,999の数値ごとに1ビットを使用します。これは1.25 MBのRAMです。
ファイルを1回読み取り、数値が読み取られたときに対応するビットをマークします。次に、2番目のパスでビットフィールドを調べ、ビットが設定されているすべてのエントリのインデックスを出力します。重複がないことを知っているので、これは機能します。最大10,000,000は、その結果です。アルゴリズムは任意の数の数値で機能します。
許可された重複がある場合にどうなるかという問題に関して、私も重複を印刷する必要があるのか、それとも数字だけを印刷する必要があるのかは明確ではありません。もちろん、後者のケースも機能しますが、前者は機能しません-追加情報を格納する必要があります。
重複なしでソートされた1000万の7桁の数値は、0、1、2、3、...、9、999、999です。
1.25 MBのメモリを使用し、線形時間で実行して、1,000万未満のヒントが得られることを願っています。
一時ファイルが毎回大きくなるため、アルゴリズムが機能せず、すぐにメモリ不足に戻ります。
数値の合計範囲をそれに応じたサイズの「バケット」に分割し、バケットごとに1つのファイルを割り当てるアプローチについて考えます。
次に、束を読み取ってバケットに割り当て、それぞれの「バケット」ファイルに追加します。
すべての数値を1回実行すると、バケットファイルが作成され、それぞれを読み取ってメモリ内で完全にソートし(正しいバケットサイズを選択した場合)、正しい順序で印刷できます。最も重要なことは、後のバケットに、すでに印刷するために必要な数が含まれていないことを確認できることです。