По второму вопросу:
Вы можете посмотреть на Bloom Filters . Фильтры Блума специально предназначены для ответа на вопрос о членстве в O (1), хотя ответ либо no
, либо maybe
(что не так ясно, как да / нет: p).
В случае maybe
, конечно, вам нужна дополнительная обработка, чтобы фактически ответить на вопрос (если в вашем случае не достаточно вероятностного ответа), но даже в этом случае Фильтр Блума может действовать как привратник и отвергать большинство из запросов прямо.
Кроме того, вы можете сохранить фактические диапазоны и вырожденные диапазоны (отдельные элементы) в разных структурах.
- отдельные элементы лучше всего хранить в хеш-таблице
- фактические диапазоны могут быть сохранены в отсортированном массиве
Это уменьшает количество элементов, хранящихся в отсортированном массиве, и, следовательно, сложность двоичного поиска, выполняемого там. Поскольку вы заявляете, что многие диапазоны являются вырожденными, я предполагаю, что у вас есть только около 500-1000 диапазонов (т. Е. На порядок меньше), и log (1000) ~ 10
Поэтому я бы предложил следующие шаги:
- Фильтр Блума: если нет, остановите
- Сортированный массив реальных диапазонов: если да, остановить
- Хеш-таблица из отдельных элементов
Тест Sorted Array выполняется первым, потому что из числа, которое вы даете (миллионы чисел объединяются в несколько тысяч диапазонов), если число содержится, скорее всего, оно будет в диапазоне, а не в одиночку :)
Последнее замечание: остерегайтесь O (1), хотя это может показаться привлекательным, вы не находитесь здесь в асимптотическом случае. Едва 5000-10000 диапазонов - это мало, так как log (10000) - это что-то вроде 13. Так что не пессимизируйте вашу реализацию, получив решение O (1) с таким высоким постоянным коэффициентом, что оно на самом деле работает медленнее, чем O (log N ) решение:)