私はこのインタビューの質問を受けました:
40 億の整数を含む入力ファイルが与えられた場合、ファイルに含まれていない整数を生成するアルゴリズムを提供します。1 GB のメモリがあるとします。メモリが 10 MB しかない場合に何をするかをフォローアップします。
私の分析:
ファイルのサイズは 4×10 9 ×4 バイト = 16 GB です。
外部ソートを実行できるため、整数の範囲を知ることができます。
私の質問は、ソートされた大きな整数セットで不足している整数を検出する最良の方法は何ですか?
私の理解(すべての回答を読んだ後):
32 ビット整数について話していると仮定すると、2 32 = 4*10 9 個の異なる整数があります。
ケース 1: 1 GB = 1 * 10 9 * 8 ビット = 80 億ビットのメモリがあります。
解決:
1 つの異なる整数を表す 1 ビットを使用すれば、それで十分です。ソートは必要ありません。
実装:
int radix = 8;
byte[] bitfield = new byte[0xffffffff/radix];
void F() throws FileNotFoundException{
Scanner in = new Scanner(new FileReader("a.txt"));
while(in.hasNextInt()){
int n = in.nextInt();
bitfield[n/radix] |= (1 << (n%radix));
}
for(int i = 0; i< bitfield.lenght; i++){
for(int j =0; j<radix; j++){
if( (bitfield[i] & (1<<j)) == 0) System.out.print(i*radix+j);
}
}
}
ケース 2: 10 MB メモリ = 10 * 10 6 * 8 ビット = 8000 万ビット
解決:
考えられるすべての 16 ビット プレフィックスには、2 16個の整数 = 65536 があり、2 16 * 4 * 8 = 200 万ビットが必要です。65536 個のバケットを構築する必要があります。最悪の場合、40 億個の整数すべてが同じバケットに属するため、バケットごとにすべての可能性を保持する 4 バイトが必要です。
- ファイルの最初のパスで各バケットのカウンターを構築します。
- バケットをスキャンして、ヒット数が 65536 未満の最初のバケットを見つけます。
- ファイルの 2 番目のパスを通じてステップ 2 で見つかった上位 16 ビット プレフィックスを持つ新しいバケットを構築します。
- ステップ 3 で構築されたバケットをスキャンし、ヒットがない最初のバケットを見つけます。
コードは上記のものと非常によく似ています。
結論: ファイル パスを増やすことでメモリを減らします。
遅れて到着した人への説明: この質問は、ファイルに含まれていない整数が 1 つだけあるとは言っていません。少なくとも、ほとんどの人はそのように解釈していません。ただし、コメント スレッドの多くのコメントは、タスクのバリエーションに関するものです。残念ながら、それをコメント スレッドに導入したコメントは後で作成者によって削除されたため、孤立した返信がすべてを誤解しているように見えます。とても紛らわしいです、すみません。