我需要一种算法来在同一行找到最大的等距点。
输入:共线点列表
例如:我的观点可能是
[(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)]
答案 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)]
>>>