第一种思路:
O
(
N
3
)
O(N^3)
O(N3).暴力枚举两点的斜率求出直线,再遍历所有点看是否在该条直线上
第二种思路:
O
(
N
2
l
o
g
M
)
O(N^2logM)
O(N2logM),N为点的数量,M为坐标区间长度。我们可以知道若3个点
i
,
j
,
k
i,j,k
i,j,k在同一条直线上,那么
i
−
j
,
和
i
−
k
i-j, 和i-k
i−j,和i−k的斜率一定是相同的,于是我们只需要从前往后以
i
i
i点开始枚举到剩余点的斜率即可,用hash表来统计每个斜率的个数。由于斜率有误差,我们利用最简分数来表示每个斜率,如
1
/
2
1/2
1/2。这样会面临2种情况,第一种是
1
/
−
2
,
−
1
/
2
1/-2, -1/2
1/−2,−1/2,我们统一规定分母为正。第二种是分子、分母出现0,直接让另外坐标为1即可,即
0
/
1
,
1
/
0
0/1, 1/0
0/1,1/0。我们可以用pair来存储分子分母,由于x的坐标最多为
[
−
2
∗
1
0
4
,
2
∗
1
0
4
]
[-2 *10^4, 2 * 10^4]
[−2∗104,2∗104],y的坐标为
[
0
,
2
∗
1
0
4
]
[0, 2 * 10^4]
[0,2∗104], 因此我们可以直接映射为一个整数,
v
a
l
=
y
+
(
2
∗
1
0
4
+
1
)
∗
x
val = y + (2 * 10^4 + 1) * x
val=y+(2∗104+1)∗x, 该整数便可以唯一表示每个最简分数。
三、代码
classSolution{public:intmaxPoints(vector<vector<int>>& points){int ans =1, n = points.size();for(int i =0; i < n; i++){for(int j = i +1; j < n; j++){//计算直线double x1 = points[i][0], y1 = points[i][1], x2 = points[j][0], y2 = points[j][1];//特殊判断x,y轴int cnt =0;if(y2 - y1 ==0){for(int h =0; h < n; h++){if(points[h][1]== y1) cnt++;}}elseif(x2 - x1 ==0){for(int h =0; h < n; h++){if(points[h][0]== x1) cnt++;}}else{double k =(y2 - y1)/(x2 - x1);double b = y2 - k * x2;for(int h =0; h < n; h++){if(abs(points[h][1]- k * points[h][0]- b)<1e-6) cnt++;}}
ans =max(cnt, ans);}}return ans;}};
classSolution{public:intgcd(int a,int b){return b ?gcd(b, a % b): a;}intmaxPoints(vector<vector<int>>& points){int ans =0, n = points.size();if(n <=2)return n;for(int i =0; i < n; i++){if(ans > n /2|| ans >= n - i)break;//2种情况
unordered_map<int,int> mp;//hash记录每个斜率下的个数for(int j = i +1; j < n; j++){//计算最简分数int x = points[i][0]- points[j][0];int y = points[i][1]- points[j][1];if(x ==0) y =1;elseif(y ==0) x =1;else{if(y <0) x =-x, y =-y;int gcd_ =gcd(x, y);
x /= gcd_, y /= gcd_;}
mp[y +(2e4+1)* x]++;//该斜率下的个数增加 }for(auto[_, num]: mp) ans =max(ans, num +1);//点的个数还要加上1}return ans;}};