解题思路:
两个for循环
以题目给的例子为例:{{1,1},{3,2},{5,3},{4,1},{2,3},{1,4}}
假如三个点point1 point2 point3在同一条直线上,则它们的斜率比值是一样的:
(point1.y-point2.y)/(point1.x-point2.x)=(point1.y-point3.y)/(point1.x-point3.x)
根据上面的式子可以计算出基于每个点的不同斜率上的点的个数。
例如对第一个点{1,1}来说,我们从第二个点开始计算dx和dy值,有:
dx,dy | 直线上的点 |
---|---|
2,1 | {1,1},{3,2},{5,3} |
0,1 | {1,1},{4,1} |
1,2 | {1,1},{2,3} |
1,0 | {1,1},{1,4} |
最多的点是斜率为dx=2 dy=1上的点,共3个。
对于第二个点,我们从第三个点开始计算不同dx和dy上的点的数量。因为在计算第一个点时,我们已经计算完了包含第一个点时所有的可能情况,所有没必要重复计算,可得:
dx,dy | 直线上的点 |
---|---|
2,1 | {3,2},{5,3} |
1,-1 | {3,2},{4,1},{2,3},{1,4} |
1,2 | {5,3},{4,1} |
1,0 | {5,3},{2,3} |
4,-1 | {5,3},{1,4} |
最多的点是斜率为dx=1,dy=-1上的点,共4个。
对剩下的点进行同样的计算可以得到总共n张表格,n是点的个数。
这里我们的内循环就是一张表中每一行的内容,外循环就是所有的表。
对于最大直线点数的更新用2个参数来维护。max表示以当前点为基点时最大的点数,例如以{1,1}为基点时最大点数是3({1,1}{3,2}{5,3}),在内循环内更新
res是我们的结果,在外循环内更新
时间复杂度:O(n^2)
空间复杂度:O(n)
提交代码:
class Solution{
public int maxPoints(Point[] points) {
if(points.length<=2) return points.length;
int res=0,duplicate=0,max=0;
Map<Integer,Map<Integer,Integer>> map=new HashMap<>();
for(int i=0;i<points.length;i++) {
map.clear();duplicate=0;max=0;
for(int j=i+1;j<points.length;j++) {
int dx=points[i].x-points[j].x;
int dy=points[i].y-points[j].y;
if(dx==0&&dy==0) {
duplicate++;
continue;
}
int gcd=getGCD(dx,dy);
if(gcd!=0) {
dx/=gcd;
dy/=gcd;
}
if(map.containsKey(dx)) {
if(map.get(dx).containsKey(dy)) {
map.get(dx).put(dy, map.get(dx).get(dy)+1);
}else {
map.get(dx).put(dy, 1);
}
}else {
Map<Integer,Integer> tmp=new HashMap<>();
tmp.put(dy, 1);
map.put(dx, tmp);
}
max=Math.max(map.get(dx).get(dy), max);
}
if(max+duplicate+1>res) res=max+duplicate+1;
}
return res;
}
private int getGCD(int a,int b) {
if(b==0) return a;
return getGCD(b,a%b);
}
}
运行结果:
扫描二维码关注公众号,回复:
4671449 查看本文章