找到给定集合中的所有共线点

时间:2010-12-29 21:04:54

标签: algorithm geometry

这是interview question:“查找给定集合中的所有共线点”。

据我所知,他们要求打印出位于同一行的点(并且每两个点总是共线的)。我建议如下。

  1. 让我们介绍两种类型Line(双打对)和Point(整数对)。
  2. 创建多图:HashMap<Line, List<Point>)
  3. 遍历所有点对和每对:计算连接点的Line,并将这些点的线添加到多图。
  4. 最后,multimap包含行作为键,并将每行的列表共线点作为其值。

    复杂度为O(N ^ 2)。是否有意义 ?有更好的解决方案吗?

6 个答案:

答案 0 :(得分:8)

这里的共线并没有多大意义,除非你先确定2点。所以说,“在给定集合中找到所有共线点”在我看来没有多大意义,除非你确定2点并测试其他点以确定它们是否共线。

也许更好的问题是,给定集合中共线点的最大数量是多少?在这种情况下,您可以修复2个点(仅使用2个循环),然后循环其他点并检查固定点和其他点之间的斜率是否匹配。假设坐标是整数,你可以使用这样的东西进行检查(否则你可以将参数类型改为double)。

// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Returns whether 3 points are collinear
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
bool collinear(int x1, int y1, int x2, int y2, int x3, int y3) {
  return (y1 - y2) * (x1 - x3) == (y1 - y3) * (x1 - x2);
}

所以逻辑变为:

int best = 2;
for (int i = 0; i < number of points; ++i) {
  for (int j = i+1, j < number of points; j++) {
    int count = 2;
    for (int k = 0; i < number of points; ++k) {
      if (k==i || k==j)
        continue;

      check that points i, j and k are collinear (use function above), if so, increment count.
    }
    best = max(best,count); 
  }
}

答案 1 :(得分:5)

解决双平面问题,将所有点转换为线段。然后运行平面扫描报告所有交叉点。双平面中的线将通过相同的点表示共线点。平面扫描可以在O(nlogn)时间内完成。

答案 2 :(得分:2)

看看http://www.cs.princeton.edu/courses/archive/spring03/cs226/assignments/lines.html中描述的两种方法。

为了找到给定N个点的4个或更多共线点,蛮力方法的时间复杂度为O(N ^ 4),但是在O(N ^ 2 log N)中有更好的方法。

答案 3 :(得分:1)

一个有趣的解决方案在这里。

时间复杂度为O(n2)

空间复杂度-O(n)

https://stackoverflow.com/a/50207802/7438973

答案 4 :(得分:0)

我认为目的是找到一条通过最大点数或识别这组共线点的线。这个link给出了这个问题的N ^ 2(logN)解决方案

答案 5 :(得分:0)

您确定您对运行时的分析是否正确?你说要遍历所有的点对,其中有n *(n-1)/ 2,即O(n ^ 2)。然后将线和一对点添加到地图中。但是,我不认为添加这样的线+点组合的时间是不变的。这意味着你的总时间是O(n ^ 2 log n)而不是n ^ 2的常数,这就是O(n ^ 2)的含义。

所以真正的问题是,鉴于它可以及时完成O(n ^ 2 log n),它可以在时间O(n ^ 2)内完成。显然,O(n ^ 2)给出一个下限,因为你必须至少打印出每对点,其中有O(n ^ 2)。我的感觉是这是一个完全一般的排序问题,并且一般不能指望比O(n ^ 2 log n)更好。然而,充分证明这一事实可能并非易事。

要注意的另一件事是该集合可能包含零个或一个点,因此您需要检查您的算法是否正确处理这些情况,否则为这些情况编写特殊情况。