Je crois que j'ai trouvé quelque chose qui devrait fonctionner de manière générale et efficace si vous êtes assuré de ne pas avoir de doublons * (cependant, il devrait être extensible à n'importe quel nombre de trous et à toute plage d'entiers).
L'idée derrière cette méthode est comme le tri rapide, en ce sens que nous trouvons un pivot et une partition autour d'elle, puis récurons sur le ou les côtés avec un trou. Pour voir quels côtés ont le trou, nous trouvons les nombres les plus bas et les plus élevés, et les comparons avec le pivot et le nombre de valeurs de ce côté. Disons que le pivot est 17 et que le nombre minimum est 11. S'il n'y a pas de trous, il devrait y avoir 6 nombres (11, 12, 13, 14, 15, 16, 17). S'il y en a 5, nous savons qu'il y a un trou de ce côté et nous pouvons recurse juste de ce côté pour le trouver. J'ai du mal à l'expliquer plus clairement que cela, alors prenons un exemple.
15 21 10 13 18 16 22 23 24 20 17 11 25 12 14
Pivot:
10 13 11 12 14 |15| 21 18 16 22 23 24 20 17 25
15 est le pivot, indiqué par les tuyaux ( ||
). Il y a 5 chiffres sur le côté gauche du pivot, comme il devrait y en avoir (15 - 10), et 9 sur la droite, où il devrait y en avoir 10 (25 - 15). Nous récurons donc du côté droit; on notera que la borne précédente était de 15 au cas où le trou lui serait adjacent (16).
[15] 18 16 17 20 |21| 22 23 24 25
Il y a maintenant 4 chiffres sur le côté gauche mais il devrait y en avoir 5 (21 - 16). Donc, nous recursons là-bas, et encore une fois, nous noterons la borne précédente (entre parenthèses).
[15] 16 17 |18| 20 [21]
Le côté gauche a les 2 bons chiffres (18 - 16), mais le droit a 1 au lieu de 2 (20 - 18). En fonction de nos conditions de fin, nous pourrions comparer le nombre 1 aux deux côtés (18, 20) et voir que 19 est manquant ou récidiver une fois de plus:
[18] |20| [21]
Le côté gauche a une taille de zéro, avec un espace entre le pivot (20) et la limite précédente (18), donc 19 est le trou.
*: S'il y a des doublons, vous pourriez probablement utiliser un ensemble de hachage pour les supprimer en temps O (N), en conservant la méthode globale O (N), mais cela pourrait prendre plus de temps que d'utiliser une autre méthode.