Вот две идеи: алгоритм аппроксимации O (n) и точный (не приближенный) алгоритм O (n ^ 2 log n):
Быстрое приближение
Используйте локальное хеширование. По сути, хэшируйте каждую точку в корзину, которая содержит все близлежащие точки. Контейнеры настроены таким образом, что коллизии происходят только между близлежащими точками - в отличие от хеш-таблиц с одинаковыми именами, здесь полезны коллизии. Ведите счетчик количества столкновений в ведре, а затем используйте центр этого ведра в качестве центра вашего круга.
Я признаю, что это быстрое объяснение концепции, которая не является супер-очевидной, когда вы впервые слышите о ней. Аналогия будет в том, чтобы спросить кучу людей, каков их почтовый индекс, и использовать самый распространенный почтовый индекс, чтобы определить самый густонаселенный круг. Это не идеально, но хорошая быстрая эвристика.
Это в основном линейное время с точки зрения количества точек, и вы можете на лету обновлять свой набор данных, чтобы постепенно получать новые ответы в постоянное время для каждой точки (постоянная относительно n = количество точек).
Подробнее о хэшах, чувствительных к локальности, в целом или о моей личной любимой версии, которая будет работать в этом случае .
Детерминистский подход лучше, чем грубая сила
Идея такова: для каждой точки поместите край круга в эту точку и проведите кругом вокруг, чтобы увидеть, какое направление содержит наибольшее количество точек. Сделайте это для всех точек, и мы найдем глобальный максимум.
Развертывание вокруг точки p может быть выполнено за n log n времени путем: (a) нахождения углового интервала для другой точки q, такого, что когда мы помещаем окружность под углом theta, то она содержит q; и (b) сортировка интервалов, чтобы мы могли маршировать / перемещаться вокруг p по линейному времени.
Таким образом, требуется O (n log n), чтобы найти лучший круг, касающийся фиксированной точки p, а затем умножить его на O (n), чтобы выполнить проверку для всех точек. Общее время O (n ^ 2 log n).