Ich habe diese Interviewfrage erhalten:
Geben Sie bei einer Eingabedatei mit vier Milliarden Ganzzahlen einen Algorithmus zum Generieren einer Ganzzahl an, die nicht in der Datei enthalten ist. Angenommen, Sie haben 1 GB Speicher. Folgen Sie Ihren Anweisungen, wenn Sie nur 10 MB Arbeitsspeicher haben.
Meine Analyse:
Die Größe der Datei beträgt 4 × 10 9 × 4 Bytes = 16 GB.
Wir können extern sortieren und so den Bereich der ganzen Zahlen kennen.
Meine Frage ist, wie man die fehlende Ganzzahl in den sortierten großen Ganzzahlensätzen am besten erkennt.
Mein Verständnis (nachdem ich alle Antworten gelesen habe):
Angenommen, es handelt sich um 32-Bit-Ganzzahlen, dann gibt es 2 32 = 4 * 10 9 verschiedene Ganzzahlen.
Fall 1: Wir haben 1 GB = 1 * 10 9 * 8 Bit = 8 Milliarden Bit Speicher.
Lösung:
Wenn wir ein Bit verwenden, das eine bestimmte Ganzzahl darstellt, reicht dies aus. Wir brauchen keine Sortierung.
Implementierung:
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);
}
}
}
Fall 2: 10 MB Speicher = 10 * 10 6 * 8 Bit = 80 Millionen Bit
Lösung:
Für alle möglichen 16-Bit-Präfixe gibt es 2 16 Ganzzahlen = 65536, wir benötigen 2 16 * 4 * 8 = 2 Millionen Bits. Wir müssen 65536 Eimer bauen. Für jeden Bucket benötigen wir 4 Bytes, die alle Möglichkeiten enthalten, da im schlimmsten Fall alle 4 Milliarden Ganzzahlen zum selben Bucket gehören.
- Erstellen Sie den Zähler jedes Buckets durch den ersten Durchgang durch die Datei.
- Scannen Sie die Eimer und finden Sie den ersten, der weniger als 65536 Treffer hat.
- Erstellen Sie neue Buckets, deren hohe 16-Bit-Präfixe in Schritt 2 bis zum zweiten Durchgang der Datei gefunden werden
- Scannen Sie die in Schritt 3 eingebauten Eimer und finden Sie den ersten Eimer, der keinen Treffer hat.
Der Code ist dem obigen sehr ähnlich.
Fazit: Wir verringern den Speicher durch Erhöhen des Dateipasses.
Eine Klarstellung für Verspätete: Die gestellte Frage besagt nicht, dass genau eine Ganzzahl nicht in der Datei enthalten ist - zumindest interpretieren die meisten Leute sie nicht so. Viele Kommentare im Kommentarthread beziehen sich jedoch auf diese Variation der Aufgabe. Leider wurde der Kommentar, der ihn in den Kommentarthread eingeführt hat, später von seinem Autor gelöscht. Jetzt sieht es so aus, als hätten die verwaisten Antworten darauf einfach alles falsch verstanden. Es ist sehr verwirrend, sorry.