找到一条线上的最大等距点

时间:2017-05-04 12:41:29

标签: python algorithm

我需要一种算法来在同一行找到最大的等距点。

输入:共线点列表

例如:我的观点可能是

[(1, 1), (1, 2), (1, 3)]

在这种情况下,我能做的是根据它们与原点的距离对点进行排序,并按顺序找到距离。但是,在诸如下面的情况下,条件失败。所有点都在同一行y=-x+6,并且彼此等距。

[(3, 3), (2, 4), (4, 2), (5, 1), (1, 5)]

因为所有点都与原点等距,并且排序顺序可以是任何顺序遍历都是不可能的。 例如,如果最终字典变成这个[(3, 3), (5, 1), (4, 2), (2, 4), (1,5)],我们最终会计算(3,3)和(5,1)之间的距离,这是不正确的。理想情况下,我想计算最近点之间的距离,因此顺序应为(1,5),(2,4)。

为了克服这个问题,我通过迭代使用2个循环创建了一个O(n * n)解决方案,并找到了任意2个点之间的最小距离的频率:

import sys
distance_list=[]
lop=[(1, 3), (2, 4), (3, 5), (4, 6), (10, 12), (11, 13), (12, 14), (13, 15), (14, 16)]
lop.sort(key=lambda x: x[0]*x[0] + x[1]*x[1])
for k in range(0, len(lop)):
    min_dist=sys.maxint
    for l in range(0, len(lop)):
        if k!=l:
            temp_dist = ( (lop[k][0] - lop[l][0])*(lop[k][0] - lop[l][0]) + (lop[k][1] - lop[l][1])*(lop[k][1] - lop[l][1]) )
            min_dist= min(min_dist, temp_dist)
    distance_list.append(min_dist)

print distance_list.count (max(distance_list,key=distance_list.count))

但是,以上测试用例的上述解决方案失败了:

[(1, 3), (2, 4), (3, 5), (4, 6), (10, 12), (11, 13), (12, 14), (13, 15), (14, 16)]

预期答案应为:5 但是,我得到了:9

基本上,我无法确定,如何区分包含等距点的2个点集群;在上面的例子中将是

[(1, 3), (2, 4), (3, 5), (4, 6)] AND [(10, 12), (11, 13), (12, 14), (13, 15), (14, 16)]

2 个答案:

答案 0 :(得分:2)

如果您想按顺序放置点,则无需按距离对它们进行排序。您可以按默认的词典顺序对它们进行排序,这与行中的顺序一致:

lop.sort()

现在你只需要弄清楚如何找到最大的等距点集。这可能很棘手,特别是如果你被允许跳过积分。

答案 1 :(得分:0)

因为你想要连续点的距离,所以不需要计算所有组合,你只需要计算(p0,p1),(p1,p2),(p2,p3)的距离,依此类推,并按照它们的距离值按顺序对这些对进行分组,一旦完成,你只需要其中最长的序列,为此itertools模块派上用场

from itertools import groupby, tee, izip  

def pairwise(iterable):
    "s -> (s0,s1), (s1,s2), (s2, s3), ..."
    a, b = tee(iterable)
    next(b, None)
    return izip(a, b)

def distance(a,b):
    ax,ay = a
    bx,by = b
    return (ax-bx)**2 + (ay-by)**2

def longest_seq(points):
    groups = [ list(g) for k,g in groupby(pairwise(points), lambda p:distance(*p)) ]
    max_s = max(groups,key=len)  # this is a list of pairs [(p0,p1), (p1,p2), (p2,p3),..., (pn-1,pn)]
    ans = [ p[0] for p in max_s ] 
    ans.append( max_s[-1][-1] ) # we need to include the last point manually 
    return ans

这里goupby函数组将连续的具有相同距离的点对成对,是成为欲望配对的recipe,其余的是自解释的。

这是一个测试

>>> test = [(1, 3), (2, 4), (3, 5), (4, 6), (10, 12), (11, 13), (12, 14), (13, 15), (14, 16)]
>>> longest_seq(test)
[(10, 12), (11, 13), (12, 14), (13, 15), (14, 16)]
>>>