L'attività è chiaramente quella di trovare un algoritmo che sia O (1) nella lunghezza N dell'elenco di numeri richiesto.
Quindi non importa se hai bisogno del numero 100 o 10000 più alto, il tempo di inserimento dovrebbe essere O (1).
Il trucco qui è che sebbene il requisito O (1) sia menzionato per la lista inserita, la domanda non ha detto nulla sull'ordine del tempo di ricerca nell'intero spazio numerico, ma risulta che questo può essere fatto O (1) pure.
La soluzione è quindi la seguente:
-
Organizzare una tabella hash con i numeri per le chiavi e le coppie di puntatori di elenchi collegati per i valori. Ogni coppia di puntatori è l'inizio e la fine di una sequenza di elenchi collegati. Normalmente questo sarà solo un elemento di quello successivo. Ogni elemento nell'elenco collegato si posiziona accanto all'elemento con il successivo numero più alto. L'elenco collegato contiene quindi la sequenza ordinata dei numeri richiesti. Conserva un record 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, portami solo qui, questo può essere migliorato e ti spiegherò come)
-
Con l'elemento della lista appena ottenuto dalla tabella hash, inserisci il nuovo numero subito dopo l'elemento nella lista collegata (e aggiorna l'hash)
-
Prendi il numero più basso l registrato (e rimuovilo dall'elenco hash /).
-
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 ascendente)
-
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 riduce l'intervallo puntato a.
L'inserto qui è O (1). Le ricerche menzionate sono, immagino qualcosa di simile, 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 da 4 byte, da 0 a 2 ^ 32-1) e N = 100. Per ovviare a questo problema di prestazioni è possibile mantenere serie parallele di hashtables, in cui i numeri sono arrotondati a magnitudini più elevate (ad esempio 1s, 10s, 100s, 1000s) per rendere le chiavi idonee. In questo modo è possibile aumentare o diminuire le marce per eseguire più rapidamente le ricerche richieste. La performance diventa quindi un O (log numberrange), penso, che è costante, cioè O (1) anche.
Per renderlo più chiaro, immagina di avere a portata di mano il numero 197. Hai colpito la tabella hash 10s, con '190', è arrotondato al dieci più vicino. Nulla? No. Quindi scendi tra 10 secondi finché non premi 120. Quindi puoi iniziare a 129 nella tabella hash, quindi provare 128, 127 fino a quando non colpisci qualcosa. Ora hai trovato dove inserire nell'elenco il numero 197. Mentre lo inserisci, devi anche aggiornare l'hash di 1s con la voce 197, l'hashtable 10s con il numero 190, 100s con 100, ecc. La maggior parte dei passaggi devi fare qui 10 volte il registro dell'intervallo numerico.
Potrei aver sbagliato alcuni dettagli, ma poiché questo è lo scambio di programmatori e il contesto è stato interviste, spero che quanto sopra sia una risposta abbastanza convincente per quella situazione.
EDIT ho aggiunto ulteriori dettagli qui per spiegare lo schema di hashtable parallelo e come significa che le ricerche lineari povere che ho menzionato possono essere sostituite con una ricerca O (1). Ho anche realizzato che ovviamente non è necessario cercare il numero più basso successivo, perché puoi passare direttamente ad esso esaminando la tabella hash con il numero più basso e passando all'elemento successivo.