Всем привет. У меня есть неупорядоченный массив точек(в моем случае

в трёхмерном пространстве). Есть критерий связанности точек: если евклидово расстояние между ними меньше заданного. Как можно за быстро найти группу связанных точек? У меня быстрее чем O(n^2) не получается.

Возможно если строить kd-дерево за O(nlogn) то можно что то выиграть?

31 ответов

62 просмотра

Что подразумевается под "группой связанных точек"? Найти какую-то компоненту связности нужного размера или разбить все точки на компоненты связности (или вообще что-то ещё)?

Павлик-Ливаткин Автор вопроса
tiom4eg 🇷🇺
Что подразумевается под "группой связанных точек"?...

что внутри группы от любой точки до любой другой есть путь по цепочке связанных точек

Можно отсортировать точки по одной координате и поддерживать множество точек, которые могут быть связаны с текущей точкой(они должны быть на расстояние не больше заданного). Так тоже в худшем случае квадрат, но должно быть быстрее

Павлик-Ливаткин Автор вопроса
Алексей Госунов
Можно отсортировать точки по одной координате и по...

да, я пытался сделать такое окно. ускорение и правда было. С 25 секунд до 12. В два раза конечно, но мне бы секунды в 2 уложиться

Павлик-Ливаткин Автор вопроса
Алексей Госунов
Можно отсортировать точки по одной координате и по...

хм... а что если от стартовой точки отсортировать не по координате, а по сферам с радиусами d, 2d, 3d, 4d, ... ? Потом начинаем от стартовой: тогда соседи точек, заключенных между сферами 1 и 2 могут быть только среди точек, заключенных между 2 и 3. И дальше итеративно. Ну хоть не всех со всеми проверять придётся. А когда первый кластер выделю - повторная разбивка на сферы от новой точки из ещё не занятых

Да, это кластеры. DBSCAN подходит, кажется.

Павлик Ливаткин
хм... а что если от стартовой точки отсортировать ...

Тут проблема, что уже в двумерном пространстве не сделаешь индекс “по сферам”, без приседаний. Это будет какой-то нетривиальный алгоритм similarity search.

Павлик-Ливаткин Автор вопроса
George Polevoy
Тут проблема, что уже в двумерном пространстве не ...

У меня есть ещё концепции, но пока я не знаю как бы их реализовать по удобному. 1) а может есть способ запихать всё в трёхмерный массив, но как то сэкономить на пустых элементах? потому что он сильно разряжен. В массиве то обход вширину легко делать. Визуально то эти кластеры легко выделяются глазами. Потому что мы не анализируем пустоту, а только сами точки 2) а может как то брать случайную точку и забыстро проверять подходит ли она к уже имеющимся кластерам?(да, во множественном числе). И если она общая для двух кластеров - объединять их. если не общая нидлякого - будет началом нового кластера 3) а как бы это дело распараллелить? количество ядер то может быть большим. а есть ещё и видеокарты

Павлик Ливаткин
У меня есть ещё концепции, но пока я не знаю как б...

Разреженная трехмерная сетка работает с помощью хэштаблицы. В трехмерном пространстве это можно сделать, если точки довольно равномерно расположены, но этот алгоритм сломается, если в каких-то зонах высокая концентрация точек, тогда получится тот же N^2 Координаты точки округляем по размеру, на который нам нужно отступать, условно - единица. Строим хэштаблицу динамических массивов, и все точки по своим округленным координатам распихиваем в эти массивы. Теперь идем по всем ключам хэштаблицы, находим 26 смежных ключей, и для каждой пары центральная - перефирийная округленная точка добавляем грани смежности в граф. Ну потом уже ищем по графу связанные подграфы.

George Polevoy
Разреженная трехмерная сетка работает с помощью хэ...

Это будет великолепно работать для равномерно распределенных точек. Если где-то большая кучность, то проверка смежности в соседних ячейках сетки будет тормозить, так как это честный квадратичный алгоритм.

Алексей Госунов
Можно отсортировать точки по одной координате и по...

Можно совместить этот приём с приёмом "разделяй и влавствуй": 1) бьём облако плоскостью по одной из координат на левое и право (предположим по медиане) 2) запускаемся рекурсивно на левом 3) запускаемся рекурсивно на правом 4) по результатам обоих запусков строим облако, которое находится на расстоянии от плоскости разбиения <= d из левого и правого (уже отсортированное по одной из координат) 5) применяем приём из реплая - опционально, на самом деле, на "плоское" облаком можно ещё раз применять итерацию нашего алгоритма, но уже по другой координате чтобы получить "линейное" облако, на линейное облаком уже можно с кайфом применять алгоритм из реплая от очень большой плотности точек это всё равно не спасёт, но кажется, что в такой ситуации не спасёт ничего

Павлик-Ливаткин Автор вопроса
George Polevoy
Разреженная трехмерная сетка работает с помощью хэ...

Вот тут вопрос: допустим я храню графы как матрицы смежности. А почему вообще надо хранить как граф? А не просто точки в массиве

Павлик Ливаткин
Вот тут вопрос: допустим я храню графы как матрицы...

Я предложил строить граф, чтобы потом, после того, как найдены грани, можно было обойти графовым алгоритмом грани, чтобы найти связные подграфы.

Павлик-Ливаткин Автор вопроса
George Polevoy
Это будет великолепно работать для равномерно расп...

Вопрос: а что если я буду хранить кластер как три avl-дерева? По х,y,z. И с номером точки, дополнительно. После этого я беру новую точку. Можно ли тогда за быстро проверить принадлежит она кластеру или нет? Спуститься по дереву по каждой из координат. Я найду ближайшую точку по х, по y и по z. Проверю только их на расстояние до добавляемой точки. Если хоть одна из них рядом - вставляю новую точку в деревья. Если все далеко - то новая точка начало нового кластера. Будет ли работать такая "быстрая" проверка на вхождение в кластер? Ну и если точка принадлежит двум кластерам - надо их как то объединять за быстро, но это уже другая история

Павлик Ливаткин
Вопрос: а что если я буду хранить кластер как три ...

Разве это будет работать для набора точек: (0, 0), (1, 5), (5, 1), (2, 2), где стартовая точка (0, 0)?

Павлик-Ливаткин Автор вопроса
Антон Novikov
Разве это будет работать для набора точек: (0, 0),...

Ну тогда ещё надо определиться с расстоянием связности и с тем какую точку добавляем. Или (0,0) - и есть стартовый кластер из одной точки?

Павлик-Ливаткин Автор вопроса
George Polevoy
Я предложил строить граф, чтобы потом, после того,...

Не могу понять что значит связные подграфы. Подграф ещё понятно - кусок текущего графа. А связный это как?

Павлик-Ливаткин Автор вопроса
George Polevoy
Разреженная трехмерная сетка работает с помощью хэ...

Ща. Кажется сообразил. Я не все точки загоняю в разреженную сетку, а потом чето анализирую в ней. Я начинаю строить графы и для каждого из графов храню свою собственную разреженную сетку. Тогда при добавлении новой точки я могу за быстро проверять: входит точка в окрестность одного из имеющихся графов или нет. Ну и объединять графы если новая точка принадлежит сразу двум как то за быстро наверное тоже смогу Так?

Антон Novikov
Можно совместить этот приём с приёмом "разделяй и ...

Окей, тогда похоже, что вот это будет работать за что-то типа O(n*k).

Павлик Ливаткин
Не могу понять что значит связные подграфы. Подгра...

Я имею в виду, что после первой стадии алгоритма, который я предлагаю, вы получите просто граф, где есть компоненты. https://en.wikipedia.org/wiki/Component_(graph_theory)

Павлик Ливаткин
Ща. Кажется сообразил. Я не все точки загоняю в ра...

Нет, единый граф строится. В нем образуются компоненты. Это части графа, между которыми нет транзитивных связей. https://en.wikipedia.org/wiki/Component_(graph_theory)

Павлик-Ливаткин Автор вопроса

возможно я то то не так понял. вот я строю граф в котором связаны все 80_000 точек. получаю 80_000^2 связей. потом все их обхожу BFS? я явно что то не так понял.. Или граф строится из кубиков, которые являются элементами хэш-таблицы?

George Polevoy
Связей будет не n^2, а столько, сколько их есть.

В этом графе будут ребра только для тех точек, которые ближе.

Павлик Ливаткин
возможно я то то не так понял. вот я строю граф в ...

Нет, я предлагал искать ребра по смежным кубикам. А сами ребра - это те точки, которые точно ближе даметра.

George Polevoy
Нет, я предлагал искать ребра по смежным кубикам. ...

Таких кубиков максимум 26 для каждого. И искать достаточно только в смежных кубиках. Все, что в них не попало - больше диаметра для любой точки вне этих кубиков, так как сторону кубика я предлагал выбрать равную диаметру, внутри которого точки считаются связанными.

Павлик-Ливаткин Автор вопроса
George Polevoy
Таких кубиков максимум 26 для каждого. И искать до...

про то что надо искать точки в соседних кубиках, а не во всём пространстве облака точек я понимаю. я а раздумьях как это сделать. а рисунок сложный чтоб пояснить в чём я вижу проблему

Павлик Ливаткин
про то что надо искать точки в соседних кубиках, а...

Сделать это просто. Берем хэштаблицу, ключ - целочисленные координаты, значение - вершины графа, котопые попали в кубик. Потом идем по всем ключам этой таблицы просто, и генерируем окрестность из 26 ключей, которые надо проверить.

Похожие вопросы

Обсуждают сегодня

Всем привет Есть достаточно базовая задача: Дан неориентированный граф. Требуется определить, есть ли в нем цикл, и, если есть, вывести его. Входные данные подаются в виде ма...
Αλeksandr
10
Привет всем. Подскажите, как можно данную задачу более менее эффективно решить? В столовой одного известного Завода вот-вот начнётся обед. На обеде есть три гарнира — макарош...
Vitaliy
6
Доброе утро. Такой вопрос: есть ли какие-то практически полезные меры вычислительной мощности (в смысле computational complexity) для реальных машин, с ограниченными ресурсам...
Yaroslav Schekin
15
Всем привет Пытаюсь решить следующую задачу: https://informatics.msk.ru/mod/statements/view.php?id=6992&chapterid=101#1 Строка S была записана много раз подряд, после чего из ...
Αλeksandr
10
Здравствуйте. Есть задача нужно найти наименшое число P где фактриал P делиться на 10^N. Ограничения 10^9. Знаю что нужно найти такой P в конце как минимум N нулей. Решение с ...
. Azmiddin
20
Друзья, практический вопрос надо счиать скользящую медиану в последовательности по заданному окну (длины N) тупой вариант - взять значения в окне, отсортировать, взять элеме...
Стас Выщепан
17
Должна-ли работать такая стратегия: Мы каждую секунду бросаем монетку - орел или решка. Если орел - покупаем акцию на все деньги, если у нас есть деньги, или продаем все акци...
George Polevoy
13
#pragma once #include <iostream> #include <vector> template <typename T, typename Comp = std::less<T>> class Heap { public: Heap() = default; Heap(const std::vector<T>&...
Степан
1
Как можно сжимать временные ряды в памяти? У меня есть исторические стоимости ценных бумаг. Данные для каждой минуты в истории OHLC (Open, High, Low, Close). Соответственно, O...
George Polevoy
10
Всем привет Есть задача про интервалы - https://ejudge.lksh.ru/archive/2014/12/Ccpp/day01/01.pdf?ysclid=lhaombs4s4535475456 Думал как решить задачу быстрее, чем за квадрат, но...
Αλeksandr
18
Карта сайта