Я считаю, что я придумал что-то, что должно работать в целом и эффективно, если вам гарантировано, что у вас не будет дубликатов * (однако это должно быть расширяемо для любого числа отверстий и любого диапазона целых чисел).
Идея, лежащая в основе этого метода, похожа на быструю сортировку, в которой мы находим стержень и разделяем его, а затем возвращаемся на сторону (и) с отверстием. Чтобы увидеть, на каких сторонах есть отверстие, мы находим самые низкие и самые высокие числа и сравниваем их с осью и количеством значений на этой стороне. Скажем, точка разворота 17, а минимальное число - 11. Если отверстий нет, должно быть 6 чисел (11, 12, 13, 14, 15, 16, 17). Если есть 5, мы знаем, что на этой стороне есть дыра, и мы можем пройти только на той стороне, чтобы найти ее. У меня проблемы с объяснением этого более четко, поэтому давайте рассмотрим пример.
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 - это ось, обозначенная трубками ( ||
). На левой стороне оси 5 цифр, как должно быть (15 - 10), и 9 справа, где должно быть 10 (25 - 15). Итак, мы возвращаемся с правой стороны; отметим, что предыдущая граница была 15 в случае, если дыра находится рядом с ней (16).
[15] 18 16 17 20 |21| 22 23 24 25
Теперь на левой стороне 4 цифры, но должно быть 5 (21 - 16). Итак, мы вернемся туда и снова отметим предыдущую границу (в скобках).
[15] 16 17 |18| 20 [21]
Левая сторона имеет правильные 2 числа (18 - 16), но правая имеет 1 вместо 2 (20 - 18). В зависимости от наших условий окончания, мы можем сравнить число 1 с двумя сторонами (18, 20) и увидеть, что 19 отсутствует, или повторить еще раз:
[18] |20| [21]
Левая сторона имеет нулевой размер с зазором между осью (20) и предыдущей границей (18), поэтому 19 - это отверстие.
*: Если есть дубликаты, вы, вероятно, могли бы использовать хэш-набор, чтобы удалить их за O (N), сохраняя общий метод O (N), но это может занять больше времени, чем при использовании какого-либо другого метода.