这是面试问题:“查找给定集合中的所有共线点”。
据我了解,他们要求打印出位于同一行的点(并且每两个点始终共线)。我建议如下。
- 我们来介绍两种类型:
Line
(双精度值对)和Point
(整数对)。
- 创建一个多重映射:
HashMap)
- 循环遍历所有点对,并为每对:计算连接点的
Line
并将线与这些点相加指向多重贴图。
最后,多重映射包含作为键的线和作为其值的每条线的共线点列表。
复杂度为O(N^2)。有道理吗?有更好的解决方案吗?
This is an interview question: "Find all collinear points in a given set".
As I understand, they ask to print out the points, which lie in the same line (and every two points are always collinear). I would suggest the following.
- Let's introduce two types
Line
(pair of doubles) and Point
(pair of integers).
- Create a multimap :
HashMap<Line, List<Point>)
- Loop over all pairs of points and for each pair: calculate the
Line
connecting the points and add the line with those points to the multimap.
Finally, the multimap contains the lines as the keys and a list collinear points for each line as its value.
The complexity is O(N^2). Does it make sense ? Are there better solutions ?
发布评论
评论(3)
除非您一开始就确定了两个点,否则共线在这里并没有真正的意义。所以说,“找到给定集合中的所有共线点”在我看来没有多大意义,除非您固定两个点并测试其他点以查看它们是否共线。
也许更好的问题是,给定集合中共线点的最大数量是多少?在这种情况下,您可以固定 2 个点(只需使用 2 个循环),然后循环其他点并检查固定点和其他点之间的斜率是否匹配。您可以使用类似的方法进行检查,假设坐标是整数(否则您可以将参数类型更改为 double)。
所以逻辑就变成了:
Collinear here doesn't really make sense unless you fix on 2 points to begin with. So to say, "find all collinear points in a given set" doesn't make much sense in my opinion, unless you fix on 2 points and test the others to see if they're collinear.
Maybe a better question is, what is the maximum number of collinear points in the given set? In that case, you could fix on 2 points (just use 2 loops), then loop over the other points and check that the slope matches between the fixed points and the other points. You could use something like this for that check, assuming the coordinates are integer (you could change parameter types to double otherwise).
So the logic becomes:
解决对偶平面中的问题,将所有点转换为线段。然后运行平面扫描以报告所有交叉点。对偶平面中经过同一点的线表示共线点。并且平面扫描可以在 O(nlogn) 时间内完成。
solve the problem in dual plane, convert all the points in to line segments. And then run a plane sweep to report all the intersections. The lines in the dual plane will pass through same point represents collinear points. And the plane sweep can be done in O(nlogn) time.
您确定您对运行时的分析是正确的吗?你说要循环遍历所有的点对,其中有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) 更好。然而,要充分证明这一事实可能并非易事。
另一件需要注意的事情是,该集合可能包含零个或一个点,因此您需要检查您的算法是否正确处理这些情况,否则为这些情况编写特殊情况。
Are you sure your analysis of the runtime is correct? You say to loop over all the pairs of points, of which there are n*(n-1)/2, i.e. O(n^2). Then you add the line and the pair of points to the map. However, I don't think the time to add such a line + point combination is constant. This means overall your time is O(n^2 log n) not a constant times n^2, which is what O(n^2) means.
So the real question would be, given that it can be done in time O(n^2 log n) can it be done in time O(n^2). Clearly O(n^2) gives a lower bound as you must at the very least print out every pair of points, of which there are O(n^2). My feeling is this is a completely general sorting problem and that one cannot expect better than O(n^2 log n) in general. However a full proof of that fact may be non-trivial.
Another thing to beware of is that the set may contain zero or one points, and so you will need to check that your algorithm handles these cases correctly, otherwise write special cases for those.