直线上最多的点数
给定一个二维平面,平面上有 n 个点,求最多有多少个点在同一条直线上。
示例 1:
输入: [[1,1],[2,2],[3,3]]
输出: 3
解释:
^
|
|
\quad
\quad
o
|
\quad
o
| o
±------------>
0 1 2 3 4
示例 2:
输入: [[1,1],[3,2],[5,3],[4,1],[2,3],[1,4]]
输出: 4
解释:
^
|
| o
|
\quad
o
\quad
\quad
o
|
\quad
\quad
o
| o
\quad
\quad
\quad
o
±------------------>
0 1 2 3 4 5 6
思路:
- 遍历点集,对于点p,统计其余点与它形成的斜率,选出最多的斜率即可。
- 我们建立n*n的表格,记录点与点之间的斜率,然后采用查表统计斜率的个数。
- 注意斜率的表示方式,这里涉及精度的问题。经过对其他博客的总结,方法为:将斜率的除数和商进行约分,然后串成一个字符串,用字符串表示斜率。
- 对于点数的统计,我们注意重复的点,最后的数目要加上重复点的个数。
代码:
class Solution {
public:
int gcd(int a, int b) //求最大公约数
{
return (b == 0) ? a : gcd(b, a%b);
}
string getSlope(int deltaX, int deltaY) //将斜率表示为deltaX+deltaY
{
if (deltaX==0 && deltaY==0) //两点一样
return to_string(0)+"+"+to_string(0);
int div=gcd(deltaX,deltaY); //最大公约数
deltaX=deltaX/div;
deltaY=deltaY/div;
return to_string(deltaX)+"+"+to_string(deltaY);
}
int maxPoints(vector<vector<int>>& points) {
int n=points.size();
if(n<=2)
return n;
//采用查表法,表格初始化
string** table=new string*[n];
for(int i=0;i<n;i++)
{
table[i]=new string[n];
}
//建表
for(int i=0;i<n;i++)
{
for(int j=i;j<n;j++)
{
int deltaX=points[i][0]-points[j][0];
int deltaY=points[i][1]-points[j][1];
table[i][j]=getSlope(deltaX,deltaY);
table[j][i]=table[i][j];
}
}
int res=1;
for(int i=0;i<n;i++)
{
int repeat=0; //重复的点
unordered_map<string,int> u_m; //记录每个斜率出现的次数
for(int j=0;j<n;j++)
{
if(table[i][j]=="0+0")
{
repeat++;
}else{
u_m[table[i][j]]++;
}
}
if(u_m.empty()) //如果全是重复的点,此时u_m为空
{
res=max(res,repeat);
}else{
for(auto &p:u_m) //u_m不为空,找出其最大值
{
res=max(res, repeat+ p.second);
}
}
}
return res;
}
};
结果:
参考链接: