题目描述
给定二维平面上的 $n$ 个点,请找出最多有多少点在一条直线上。
样例1
输入:[[1,1],[2,2],[3,3]]
输出:3
解释:
^
|
| o
| o
| o
+------------->
0 1 2 3 4
样例2
输入:[[1,1],[3,2],[5,3],[4,1],[2,3],[1,4]]
输出:4
解释:
^
|
| o
| o o
| o
| o o
+------------------->
0 1 2 3 4 5 6
算法
(哈希表) $O(n^2)$
先枚举一个定点,然后将其它点按斜率分组,斜率指与定点连线的斜率,分组可以利用哈希表。
由于一个定点加斜率可以唯一确定一条直线,所以被分到同一组的点都在一条直线上。组中点数的最大值就是答案。
特殊情况:
- 竖直直线不存在斜率,需要单独计数;
- 与定点重合的点可以被分到所有组中,需要单独处理;
另外,为了避免精度问题,此题中的斜率用 long double
存储。
时间复杂度分析:总共枚举 $n$ 个定点,对于每个定点再枚举 $n-1$ 个其余点,枚举后哈希表操作的时间复杂度是 $O(1)$,所以总时间复杂度是 $O(n^2)$。
C++ 代码
/**
* Definition for a point.
* struct Point {
* int x;
* int y;
* Point() : x(0), y(0) {}
* Point(int a, int b) : x(a), y(b) {}
* };
*/
class Solution {
public:
int maxPoints(vector<Point>& points) {
if (points.empty()) return 0;
int res = 1;
for (int i = 0; i < points.size(); i ++ )
{
unordered_map<long double, int> map;
int duplicates = 0, verticals = 1;
for (int j = i + 1; j < points.size(); j ++ )
if (points[i].x == points[j].x)
{
verticals ++ ;
if (points[i].y == points[j].y) duplicates ++ ;
}
for (int j = i + 1; j < points.size(); j ++ )
if (points[i].x != points[j].x)
{
long double slope = (long double)(points[i].y - points[j].y) / (points[i].x - points[j].x);
if (map[slope] == 0) map[slope] = 2;
else map[slope] ++ ;
res = max(res, map[slope] + duplicates);
}
res = max(res, verticals);
}
return res;
}
};
发现y总后来讲力扣时的代码看着比这个简洁很多,真的是越来越优秀啊
需要算gcd然后分数表示
这个主意好,可以有效避免浮点数精度带来的问题。
python 在这个case[[0,0],[94911151,94911150],[94911152,94911151]]的时候float的结果:0.999999989463830285529866159777157008647918701171875
0.999999989463830285529866159777157008647918701171875
1; 都不够,大佬有什么好的办法解决吗?
可以尝试一下,把所有浮点数都保留6位小数。