Il compito è chiaramente quello di trovare un algoritmo O (1) nella lunghezza N dell'elenco di numeri richiesto. Quindi non importa se hai bisogno dei primi 100 numeri o 10000 numeri, il tempo di inserimento dovrebbe essere O (1).
Il trucco qui è che sebbene quel requisito O (1) sia menzionato per l'inserimento della lista, la domanda non ha detto nulla sull'ordine del tempo di ricerca nell'intero spazio numerico, ma si scopre che questo può essere fatto O (1) anche. La soluzione è quindi la seguente:
Organizzare una tabella hash con numeri per chiavi e coppie di puntatori di elenchi collegati per valori. Ogni coppia di puntatori è l'inizio e la fine di una sequenza di elenchi collegati. Normalmente questo sarà solo un elemento e poi il successivo. Ogni elemento nell'elenco collegato va accanto all'elemento con il successivo numero più alto. L'elenco collegato contiene quindi la sequenza ordinata dei numeri richiesti. Tenere un registro del numero più basso.
Prendi un nuovo numero x dal flusso casuale.
È superiore all'ultimo numero più basso registrato? Sì => Passaggio 4, No => Passaggio 2
Premi la tabella hash con il numero appena preso. C'è una voce? Sì => Passaggio 5. No => Prendi un nuovo numero x-1 e ripeti questo passaggio (questa è una semplice ricerca lineare verso il basso, porta con me qui, questo può essere migliorato e spiegherò come)
Con l'elemento elenco appena ottenuto dalla tabella hash, inserire il nuovo numero subito dopo l'elemento nell'elenco collegato (e aggiornare l'hash)
Prendi il numero più basso l registrato (e rimuovilo dall'hash / lista).
Premi la tabella hash con il numero appena preso. C'è una voce? Sì => Passaggio 8. No => Prendi un nuovo numero l + 1 e ripeti questo passaggio (questa è una semplice ricerca lineare verso l'alto)
Con un colpo positivo il numero diventa il nuovo numero più basso. Vai al passaggio 2
Per consentire valori duplicati, l'hash deve effettivamente mantenere l'inizio e la fine della sequenza di elenchi collegati di elementi duplicati. L'aggiunta o la rimozione di un elemento in una determinata chiave aumenta o diminuisce l'intervallo indicato.
L'inserto qui è O (1). Le ricerche citate sono, immagino qualcosa del genere, O (differenza media tra i numeri). La differenza media aumenta con la dimensione dello spazio numerico, ma diminuisce con la lunghezza richiesta dell'elenco di numeri.
Quindi la strategia di ricerca lineare è piuttosto scarsa, se lo spazio numerico è grande (ad esempio per un tipo int a 4 byte, da 0 a 2 ^ 32-1) e N = 100. Per ovviare a questo problema di prestazioni è possibile mantenere serie parallele di hashtable, in cui i numeri sono arrotondati a magnitudini più elevate (ad es. 1s, 10s, 100s, 1000s) per creare chiavi adatte. In questo modo è possibile aumentare o ridurre le marce per eseguire più rapidamente le ricerche richieste. La performance diventa quindi una O (log numberrange), penso, che è costante, cioè anche O (1).
Per chiarire questo, immagina di avere a portata di mano il numero 197. Colpisci la tabella hash 10s, con '190', viene arrotondata alle dieci più vicine. Nulla? No. Quindi scendi tra 10 secondi fino a quando non premi 120, quindi puoi iniziare a 129 nell'hashtable 1s, quindi prova 128, 127 fino a quando non colpisci qualcosa. Ora hai trovato dove nell'elenco collegato inserire il numero 197. Mentre lo inserisci, devi anche aggiornare la tabella 1s con la voce 197, la tabella 10s con il numero 190, 100s con 100, ecc. Il maggior numero di passaggi devi mai fare qui sono 10 volte il registro dell'intervallo di numeri.
Potrei aver sbagliato alcuni dettagli, ma poiché si tratta dello scambio di programmatori e il contesto era interviste, spero che quanto sopra sia una risposta abbastanza convincente per quella situazione.
EDIT Ho aggiunto alcuni dettagli extra qui per spiegare lo schema di hashtable parallelo e come significhi che le scarse ricerche lineari che ho citato possono essere sostituite con una ricerca O (1). Ho anche capito che ovviamente non è necessario cercare il numero più basso successivo, perché puoi passare direttamente ad esso guardando nella tabella con il numero più basso e passando all'elemento successivo.