私はこのインタビューの質問を与えられました:
入力ファイルに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 = 2万ビットを。65536バケットを作成する必要があります。最悪の場合、40億の整数はすべて同じバケットに属するため、バケットごとに、すべての可能性を保持する4バイトが必要です。
- ファイルの最初のパスで各バケットのカウンターを作成します。
- バケットをスキャンして、ヒットが65536未満の最初のバケットを見つけます。
- ファイルの2番目のパスを介してステップ2で検出された上位16ビットのプレフィックスを持つ新しいバケットを作成します。
- 手順3で作成されたバケットをスキャンし、ヒットしていない最初のバケットを見つけます。
コードは上記のものと非常に似ています。
結論:ファイルパスを増やすことでメモリを減らします。
遅れて到着する場合の説明:質問のように、ファイルに含まれていない整数が1つしかないという質問はありません。少なくとも、ほとんどの人がそれを解釈しているわけではありません。コメントスレッドの多くのコメントがあるものの、タスクの変動について。残念ながら、コメントスレッドに導入されたコメントは後でその作成者によって削除されたため、孤立した返信はすべて誤解されているように見えます。非常に混乱しています。