【leetcode】149.(Hard)Max Points on a Line
阿新 • • 發佈:2018-12-27
解題思路:
兩個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);
}
}
執行結果: