题目描述
描述:给定一个二维平面及平面上的 N 个点列表Points,其中第i个点的坐标为Points[i]=[Xi,Yi]。请找出一条直线,其通过的点的数目最多。
设穿过最多点的直线所穿过的全部点编号从小到大排序的列表为S,你仅需返回[S[0],S[1]]作为答案,若有多条直线穿过了相同数量的点,则选择S[0]值较小的直线返回,S[0]相同则选择S[1]值较小的直线返回。
示例:
输入: [[0,0],[1,1],[1,0],[2,0]]
输出: [0,2]
解释: 所求直线穿过的3个点的编号为[0,2,3]
提示:
2 <= len(Points) <= 300
len(Points[i]) = 2
解题思路
思路1:最直观的想法是,按照编号顺序,先固定两个点i和j,两个点肯定可以确定一条直线,即初始cnt等于2,然后再遍历后面的点k,判断k是否在i和j所构成的直线上,如果在则将cnt加一,遍历完k后,再判断cnt是否大于maxCnt,如果是则更新maxCnt,并将两个点编号更新为i和j。
vector<int> bestLine(vector<vector<int>>& points)
{
int maxCnt=0;
vector<int> res(2);
for(int i=0;i<points.size();i++)
{
for(int j=i+1;j<points.size();j++)
{
//先固定两个点
int cnt=2;
long x1=points[i][0]-points[j][0];
long y1=points[i][1]-points[j][1];
for(int k=j+1;k<points.size();k++)
{
long x2=points[i][0]-points[k][0];
long y2=points[i][1]-points[k][1];
//如果斜率相等则表示在同一条直线上
if(x1*y2==x2*y1)
cnt++;
}
if(cnt>maxCnt)
{
maxCnt=cnt;
res[0]=i;
res[1]=j;
}
}
}
return res;
}
总结:注意,判断i、j、k三点是否在同一直线上,可以判断(xi-xj)/(yi-yj)是否与(xi-xk)/(yi-yk)相等,又由于可能存在xi=xj或者xi=xk的情况,即直线为垂直线,故将除法转换为乘法,即判断(xi-xj)*(yi-yk)与(xi-xk)*(yi-yj)是否想等。