是否有一种已知的有效算法可以在云中找到最接近的三个点组?
这类似于closest pair of points problem,但我正在寻找三点而不是两点。
修改
“最接近”的定义将影响算法的复杂性。正如Jack指出的那样,找到最小的区域三角形是3sum-hard,并且在任何情况下都不适合我的应用程序。
我希望有一种更有效的算法来找到最小的 perimiter (即| AB | + | AC | + | BC |)三角形或类似的东西(例如最小| AB |²+ | AC |²+ | BC |²。)我知道为什么这应该是3sum-hard,因为其他地方存在3个共线点不会影响结果。
注意:我的点有八个维度,因此任何限制为较少维度的算法都不合适。
答案 0 :(得分:5)
这个问题类似于在一组点中找到最接近的对的经典问题。您可以调整解决最近对问题的最坏情况 O(n log n)算法来解决这个问题。
Google的Code Jam竞赛中出现了具体问题。 这是分析的简历:
点数可能非常大,因此我们需要一种有效的算法。我们可以使用分而治之来解决 O(n log n)时间内的问题。我们将通过垂直线将点集分成两组相等的大小。最小周长三角形现在有三种情况:它的三个点可以完全在左侧,完全在右侧,也可以使用每半个点。
此外:
“找到第三种情况的最小周长(如果小于p)”:
我们可以证明框中的点数最多为16,因此我们每个点最多只需要考虑一个小的恒定数量的三角形。
在我看来,您甚至可以调整该方法以适用于| AB |²+ | AC |²+ | BC |²情况。
答案 1 :(得分:3)
有一种明显的算法适用于O(n^2)
。
1)执行Delaunay triangluation - O(n log n)
,因此我们得到一个平面图。
由于Delaunay三角化最大化了最小角度,很明显最近的3个点必须至少连接2个边缘(但它们不一定需要形成三角形!)。否则会有更近的点或更多的闭合角度。
2)对于每个点(图的顶点),我们检查每对相邻边并查看由这两个边定义的3个顶点。
步骤2)需要多长时间?由于图是平面的,number of edges is <= 3n - 6, i.e. O(n)
。因此,在最坏的情况下,此步骤将采用O(n^2)
(在典型情况下O(n)
,其中每个顶点的程度是有限的)。
所以整个算法都是O(n^2)
。请注意,步骤2)在某种程度上是天真的(蛮力)解决方案,所以我认为还有一个改进的空间(同样,步骤1和2可能会以某种方式合并)。
答案 2 :(得分:0)
你提到的问题是3sum难题的变化。有关详细信息,请查看http://www.cs.mcgill.ca/~jking/papers/3sumhard.pdf。
这个问题也可以表示为从给定点找到最小的三角形。
编辑:
基本上,3sum难问题意味着下界是O(n ^ 2)。这里和那里可能会有很小的改进但是没有什么可以做的。
对于此特定问题(最小三角形),请参阅http://www.cs.princeton.edu/~chazelle/pubs/PowerDuality.pdf的第3章。
答案 3 :(得分:0)
这是k-nearest neighbor问题的一种特定形式,即k = 3。引用的页面没有指定算法的复杂性,但是很明显看到一种简单的方法来计算从选定点到所有其他点的距离,然后计算从该点到所有其他点的距离,以及距离我们对新选择的点的原始点是O(n k-1 )。考虑伪代码:
for pointB in searchSpace do:
distanceAB := calculateDistance(pointA, pointB)
for pointC in {searchSpace} - {pointB} do:
distanceBC := calculateDistance(pointB, pointC)
distanceCA := calculateDistance(pointC, pointA)
if (distanceAB + distanceBC + distanceCA) < currentMin then:
currentMin := distanceAB + distanceBC + distanceCA
closestPoints := {pointA, pointB, pointC}
请注意,我们假设pointA
已从searchSpace
中移除。这是一个O(n 2 )算法。假设维度相对较小,或者函数calculateDistance
与维度呈线性增长或更小,这就为解决方案提供了合适的时间约束。当然可以进行优化,但可能不需要它们。
如果您想查看一些真实的代码,维基百科有many links到implementations。