Ваша boolean[][]
не является хорошей структурой данных для этой проблемы, по крайней мере, если она не очень плотная (например, обычно точка с крупным планом доступна в окружающем квадрате 3 × 3 или, возможно, 5 × 5).
Вам нужна двумерная карта с поиском ближайшего соседа. Полезная структура данных для этой цели - QuadTree . Это дерево степени 4, используемое для представления пространственных данных. (Я описываю здесь "Region QuadTree с точечными данными".)
По сути, он делит прямоугольник на четыре прямоугольника примерно одинакового размера и подразделяет каждый из прямоугольников далее , если в нем более одной точки .
Таким образом, узел в вашем дереве является одним из них:
- пустой листовой узел (соответствующий прямоугольнику без точек в нем)
- листовой узел, содержащий ровно одну точку (соответствующую прямоугольнику с одной точкой в нем)
- внутренний узел с четырьмя дочерними узлами (соответствует прямоугольнику с несколькими точками в нем)
(В реализациях мы можем заменить пустые конечные узлы нулевым указателем в его родительском элементе.)
Чтобы найти точку (или «узел, в котором будет находиться точка»), мы начнем с корневого узла, посмотрим, находится ли наша точка на севере / юге / востоке / западе от точки разделения, и перейдем к соответствующему дочернему элементу. узел. Мы продолжаем это, пока не достигнем какого-то конечного узла.
Для добавления новой точки мы либо получим пустой узел - тогда мы можем поставить новую точку здесь. Если мы окажемся в узле, в котором уже есть точка, создадим четыре дочерних узла (разделив прямоугольник) и добавим обе точки в соответствующий дочерний узел. (Это может быть то же самое, затем повторите рекурсивно.)
Для поиска ближайшего соседа мы либо получим пустой узел - затем вернемся на один уровень назад и посмотрим на другие дочерние узлы этого родителя (сравнивая каждое расстояние). Если мы достигаем дочернего узла с одной точкой, мы измеряем расстояние нашей точки поиска до этой точки. Если это меньше, чем расстояние до краев или узла, мы закончили. В противном случае нам также придется посмотреть на точки в соседних узлах и сравнить результаты здесь, взяв минимум. (Думаю, нам нужно рассмотреть не более четырех пунктов).
Для удаления, после нахождения точки, мы делаем ее узел пустым. Если родительский узел теперь содержит только одну точку, мы заменим его листовым узлом с одной точкой.
Поиск и добавление / удаление выполняются в O (глубина) сложности времени, где максимальная глубина ограничена log ((длина карты + ширина) / минимальное расстояние двух точек в вашей структуре) , и средняя глубина зависит от распределения точек (например, среднего расстояния до следующей точки), более или менее.
Необходимое пространство зависит от количества точек и средней глубины дерева.
Существуют некоторые варианты этой структуры данных (например, разбиение узла только тогда, когда в нем больше, чем X точек, или разделение не обязательно в середине), чтобы оптимизировать использование пространства и избежать слишком больших глубин дерева .