这是interview question:“查找给定集合中的所有共线点”。
据我所知,他们要求打印出位于同一行的点(并且每两个点总是共线的)。我建议如下。
Line
(双打对)和Point
(整数对)。HashMap<Line, List<Point>)
Line
,并将这些点的线添加到多图。最后,multimap包含行作为键,并将每行的列表共线点作为其值。
复杂度为O(N ^ 2)。是否有意义 ?有更好的解决方案吗?
答案 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)
答案 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)更好。然而,充分证明这一事实可能并非易事。
要注意的另一件事是该集合可能包含零个或一个点,因此您需要检查您的算法是否正确处理这些情况,否则为这些情况编写特殊情况。