【问题标题】:Find maximum equidistant points on a line在一条线上找到最大等距点
【发布时间】:2017-05-04 12:41:28
【问题描述】:

我需要一个算法来找到同一条线上的最大等距点数。

输入:共线点列表

例如:我的积分可能是

[(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)。

为了克服这个问题,我创建了一个 O(n*n) 解决方案,方法是使用 2 个循环进行迭代,并找到任意 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)]

【问题讨论】:

  • 您能否提供一些代码来展示您的尝试?
  • 失败是什么意思?如果它们都与原点等距,则任何顺序都是正确的排序顺序......这就像对相同数字的数组进行排序
  • 我需要一个算法来解决旅行商问题。
  • @DeepSpace 那么也许你可以问自己的问题。
  • @Nuageux 添加了代码

标签: python algorithm


【解决方案1】:

如果您想按顺序排列这些点,则无需按与任何事物的距离对它们进行排序。您可以按照默认的字典顺序对它们进行排序,这与沿线的顺序一致:

lop.sort()

现在你只需要弄清楚如何找到最大的等距点集。这可能会很棘手,尤其是在允许您跳过分数的情况下。

【讨论】:

  • 谢谢!我从来没有意识到默认排序是这样做的!
【解决方案2】:

因为要连续点的距离,所以不需要计算所有的组合,只需要计算(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 函数将具有相同距离的连续点对组合在一起,pairwise 是一个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)]
>>> 

【讨论】:

  • 感谢您的回答,但这并不能解决我提到的第二个问题,即点可能在同一条线上,并且距离不是找到连续点的必要标准。例如,通过将您的代码用于列表: test = [(3, 3), (2, 4), (4, 2), (5, 1), (1, 5)] 我得到:[ (3, 3), (2, 4)] 作为答案,正确答案是包含所有 5 个元素的整个列表
  • 仅供参考:输入列表不一定按顺序
  • 我知道了 list.sort() 为我进行排序,谢谢!
猜你喜欢
  • 2012-01-20
  • 1970-01-01
  • 2023-02-07
  • 1970-01-01
  • 2019-10-31
  • 2023-03-06
  • 2020-05-07
  • 1970-01-01
  • 2019-12-16
相关资源
最近更新 更多