Credo di aver escogitato qualcosa che dovrebbe funzionare in modo generale ed efficiente se si ha la certezza di non avere duplicati * (tuttavia, dovrebbe essere estendibile a qualsiasi numero di fori e qualsiasi intervallo di numeri interi).
L'idea alla base di questo metodo è come quicksort, in quanto troviamo un perno e una partizione attorno ad esso, quindi ricorrere sui lati con un buco. Per vedere quali lati hanno il buco, troviamo i numeri più bassi e più alti e li confrontiamo con il perno e il numero di valori su quel lato. Supponi che il perno sia 17 e il numero minimo sia 11. Se non ci sono buchi, dovrebbero esserci 6 numeri (11, 12, 13, 14, 15, 16, 17). Se ce ne sono 5, sappiamo che c'è un buco su quel lato e possiamo ricorrere su quel lato per trovarlo. Ho difficoltà a spiegarlo più chiaramente di così, quindi facciamo un esempio.
15 21 10 13 18 16 22 23 24 20 17 11 25 12 14
Perno:
10 13 11 12 14 |15| 21 18 16 22 23 24 20 17 25
15 è il perno, indicato da pipe ( ||
). Ci sono 5 numeri sul lato sinistro del perno, come dovrebbero esserci (15 - 10), e 9 a destra, dove dovrebbero esserci 10 (25 - 15). Quindi ricerchiamo sul lato destro; noteremo che il limite precedente era 15 nel caso in cui il buco sia adiacente ad esso (16).
[15] 18 16 17 20 |21| 22 23 24 25
Ora ci sono 4 numeri sul lato sinistro, ma dovrebbero essercene 5 (21-16). Quindi ricontattiamo lì e di nuovo noteremo il limite precedente (tra parentesi).
[15] 16 17 |18| 20 [21]
La parte sinistra ha i 2 numeri corretti (18 - 16), ma la destra ha 1 invece di 2 (20 - 18). A seconda delle nostre condizioni finali, potremmo confrontare il numero 1 con i due lati (18, 20) e vedere che manca 19 o ricorrere ancora una volta:
[18] |20| [21]
Il lato sinistro ha una dimensione pari a zero, con uno spazio tra il perno (20) e il limite precedente (18), quindi 19 è il buco.
*: Se ci sono duplicati, probabilmente potresti usare un set di hash per rimuoverli nel tempo O (N), mantenendo il metodo generale O (N), ma ciò potrebbe richiedere più tempo rispetto all'uso di qualche altro metodo.