Как наиболее эффективно рассчитать максимальное расстояние между двумя точками в списке?
У меня есть список L
из точек (x, y)
и обычная евклидова мера расстояния
Как найти максимальное расстояние между двумя точками в этом списке? Или, более формально: как мне найти
Тривиальный подход
Самый простой способ решить эту проблему - попробовать все:
def find_max_dist(L):
max_dist = d(L[0], L[1])
for i in range(0, len(L)-1):
for j in range(i+1, len(L):
max_dist = max(d(L[i], L[j]), max_dist)
return max_dist
Чтобы ускорить вычисления, я могу использовать квадратное расстояние в циклах и вернуть корень в конце.
Этот подход имеет сложность во время выполнения где n
длина списка L
, (И постоянная космическая сложность).
Выпуклый корпус
Очевидно, что не может быть алгоритма, который работает быстрее, чем O(n), так как нужно хотя бы один раз посмотреть на каждый элемент в списке.
Наибольшее расстояние будет между элементами выпуклой оболочки. Но легко доказать, что вычисление выпуклой оболочки по крайней мере в O(n log n)
и сканирование Грэма, кажется, делает это. Но после нахождения сложного корпуса мне все равно нужно пройти максимальное расстояние. Так что я бы в конечном итоге
def find_max_dist_graham_triv(L):
H = Graham_scan(L)
return find_max_dist(L)
Это точка, в которой я не уверен. Я думаю, что можно улучшить это так:
def find_max_dist_graham_c1(L):
H = Graham_scan(L) # Get ordered list of convex hull points
max_dist = d(L[0], L[1])
for i in range(0, len(L)-1):
loop_max_dist = 0
for j in range(i+1, len(L):
curr_dist = d(L[i], L[j])
if curr_dist < loop_max_dist:
break
loop_max_dist = curr_dist
max_dist = max(loop_max_dist, max_dist)
return max_dist
Идея состоит в том, что когда вы берете одну точку выпуклой оболочки и начинаете с соседней точки, диагонали продолжают увеличиваться, доходят до максимума, а затем продолжают уменьшаться. Хотя я не уверен, правда ли это.
Интуитивно понятно, что я бы продолжил улучшать алгоритм: как только закончится первый внутренний цикл, мы нашли "самую длинную диагональ" этого цикла. Эта диагональ разделяет все остальные точки корпуса на два несвязных множества. Каждая более длинная диагональ должна состоять из точек обоих этих наборов (правильно?):
def find_max_dist_graham_c1(L):
H = Graham_scan(L) # Get ordered list of convex hull points
max_dist = d(L[0], L[1]) # Get a fist idea what the longest distance might be
i = 0
p1 = L[i] # Grab a random point
loop_max_dist = 0
for j in range(1, len(L):
curr_dist = d(L[i], L[j])
if curr_dist < loop_max_dist:
break
loop_max_dist = curr_dist
max_dist = max(loop_max_dist, max_dist)
# Every diagonal that is longer than the best one found with L[0]
# has to have points in both of the following two sets (correct?):
# [1...j] and [j+1...len(L)]
# Try to find a neighboring diagonal that is longer.
change = True
while change:
change = False
if d(L[i-1], L[j+1]) > max_dist:
max_dist = d(L[i-1], L[j+1])
i -= 1
j += 1
change = True
elif d(L[i+1], L[j-1]) > max_dist:
max_dist = d(L[i+1], L[j-1])
i += 1
j -= 1
change = True
return max_dist
Каждая точка P на выпуклой оболочке имеет точку Q на выпуклой оболочке, так что PQ является самой длинной диагональю, включая P. Но тогда P также является "конечной точкой" для самой длинной диагонали Q?
Я действительно не уверен, что этот алгоритм правильный. Это было бы в O(n log n).
Я думаю, что проблема хорошо проанализирована, так что, может, кто-нибудь оставит несколько заметок для этого?
Хотя у меня было много подвопросов, главный вопрос:
Как эффективно найти максимальное расстояние между точками в списке точек?
3 ответа
Вы должны посмотреть на вращающиеся штангенциркули ( http://en.wikipedia.org/wiki/Rotating_calipers) - они широко используются для решения подобных проблем. Кроме того, ваше предположение неверно. Для фиксированной точки p на выпуклом многоугольнике: диагональ может сначала увеличиваться, затем уменьшаться, затем увеличиваться, а затем снова уменьшаться. По крайней мере, у меня есть случай, когда это происходит.
Эвристический подход также: выберите точку х. Найдите самую дальнюю точку y из нее. Найдите самую дальнюю точку z от y. d (z, y) - хорошая оценка.
Изображение, которое иллюстрирует диагонали:
1-> 2: увеличивается; 2->3 уменьшается; 3->4 увеличивается; 4->5 уменьшается. Рисунок может быть не точным, переместите точки, которые указывают точки 3 и 4, немного дальше от p (на той же линии).
Предполагая, что у вас равномерное распределение точек, вы можете сделать следующее:
найти max_x
а также min_x
максимальная и минимальная координаты X - (O(n)
). Эти значения должны помочь вам выбрать постоянную k
как "лучший" для текущего набора баллов. Разное значение k
будет влиять только на сложность алгоритма.
Рассмотрим новую структуру данных, которая подобна матрице и является вектором векторов или вектором связанных списков, давайте назовем ее structure
где structure[i]
является соответствующим вектором / связанными списками (как описано выше). Заполните эту структуру данных следующим образом: structure[i]
должны содержать точки, которые имеют свои x
координата находится в диапазоне [max_x+ik,max_x+(i+1)k]
это займет другое O(n)
время и O(n)
дополнительное пространство Теперь вы сортируете каждую запись structure[i]
от y
координат. После этого достаточно вычислить расстояния (грубую силу) между следующим набором точек: structure[0]
, structure[structure.length()-1]
крайности (вход в первый и последний индекс) всех остальных structure[i]
,
По сути, это почти то же самое, что выполнить выпуклый корпус и начать вычислять расстояния между точками, которые находятся на корпусе, разница в том, что выбор правильного k
может сделать это быстрее или медленнее. Имея сложность наихудшего случая O(n^2)
и лучший случай сложности O(nLg(n))
, куда k
будет влиять на торговлю либо сортировкой больших групп точек, либо наличием большего количества точек для вычисления расстояний между ними.
Максимальное расстояние между точками в E2 и E3 для БОЛЬШИХ наборов данных
Для больших наборов данных, даже если O(N lgN) велико, полезно посмотреть на
Скала,V.: Быстрый ожидаемый (N) алгоритм для нахождения точного максимального расстояния в E2 вместо O(N2) или O(N lgN), http://herakles.zcu.cz/~skala/PUBL/PUBL_2013/2013_ICNAAM-FastOexpected-Max-Distance.pdf
Скала В., Майдисова З., Смолик М. М.: Быстрый алгоритм определения максимального расстояния с пространственным делением в E2, появившийся в ICIG2015, Китай, - скоро будет доступен через http://herakles.zcu.cz/~skala/publications.htm
Skala