Mi è stata data questa domanda di intervista:
Dato un file di input con quattro miliardi di numeri interi, fornire un algoritmo per generare un numero intero non contenuto nel file. Supponiamo di avere 1 GB di memoria. Segui cosa faresti se avessi solo 10 MB di memoria.
La mia analisi:
La dimensione del file è 4 × 10 9 × 4 byte = 16 GB.
Possiamo fare l'ordinamento esterno, facendoci così conoscere l'intervallo degli interi.
La mia domanda è: qual è il modo migliore per rilevare il numero intero mancante nei set di numeri interi grandi ordinati?
La mia comprensione (dopo aver letto tutte le risposte):
Supponendo che stiamo parlando di interi a 32 bit, ci sono 2 32 = 4 * 10 9 interi distinti.
Caso 1: abbiamo 1 GB = 1 * 10 9 * 8 bit = 8 miliardi di memoria.
Soluzione:
Se usiamo un bit che rappresenta un intero distinto, è sufficiente. non abbiamo bisogno dell'ordinamento.
Implementazione:
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);
}
}
}
Caso 2: 10 MB di memoria = 10 * 10 6 * 8 bit = 80 milioni di bit
Soluzione:
Per tutti i possibili prefissi a 16 bit, ci sono 2 16 numero di numeri interi = 65536, abbiamo bisogno di 2 16 * 4 * 8 = 2 milioni di bit. Abbiamo bisogno di costruire 65536 secchi. Per ogni bucket, abbiamo bisogno di 4 byte con tutte le possibilità perché nel caso peggiore tutti i 4 miliardi di numeri interi appartengono allo stesso bucket.
- Costruisci il contatore di ogni bucket attraverso il primo passaggio del file.
- Scansiona i secchi, trova il primo con meno di 65536 colpi.
- Costruisci nuovi bucket i cui alti prefissi a 16 bit sono stati trovati nel passaggio 2 attraverso il secondo passaggio del file
- Analizza i bucket incorporati nel passaggio 3, trova il primo bucket che non ha un successo.
Il codice è molto simile a quello sopra.
Conclusione: riduciamo la memoria aumentando il passaggio dei file.
Un chiarimento per chi arriva in ritardo: la domanda, come posta, non dice che esiste esattamente un numero intero che non è contenuto nel file, almeno non è così che la maggior parte delle persone lo interpreta. Molti commenti nel commento filo sono circa che la variazione del compito, però. Sfortunatamente il commento che lo ha introdotto nel thread dei commenti è stato successivamente eliminato dal suo autore, quindi ora sembra che le risposte orfane ad esso abbiano frainteso tutto. È molto confuso, scusa.
int getMissingNumber(File inputFile) { return 4; }
( riferimento )