Max Points on a line
Given n points on a 2D plane, find the maximum number of points that lie on the same straight line.
Brute Force的做法,N個點兩兩可以構成N(N-1)/2條線,我們可以找這N(N-1)/2條線中線上點數最大值,只需對每一條線再進行一層O(N)的遍歷,總共是O(N^3)。
用第二種方法更好,選一個基準點, 看後面每一個點跟它構成的直線, 維護一個HashMap, key是跟這個點構成直線的斜率的值, 而value就是該斜率對應的點的數量, 計算它的斜率, 如果已經存在, 那麽就多添加一個點, 否則創建新的key。 這裏只需要考慮斜率而不用考慮截距是因為所有點都是對應於一個參考點構成的直線, 只要斜率相同就必然在同一直線上。 最後取map中最大的值, 就是通過這個點的所有直線上最多的點的數量。 對於每一個點都做一次這種計算, 並且後面的點不需要看掃描過的點的情況了, 因為如果這條直線是包含最多點的直線並且包含前面的點, 那麽前面的點肯定統計過這條直線了。 因此算法總共需要兩層循環, 外層進行點的叠代, 內層掃描剩下的點進行統計, 時間復雜度是O(n^2), 空間復雜度是哈希表的大小, 也就是O(n), 比起上一種做法用這裏用哈希表空間省去了一個量級的時間復雜度。
/** * Definition for a point. * class Point { * int x; * int y; * Point() { x = 0; y = 0; } * Point(int a, int b) { x = a; y = b; } * } */ public class Solution { public int maxPoints(Point[] points) { if (points==null || points.length==0) return 0; int allTimeMax = 0; for (int i=0; i<points.length; i++) { HashMap<Double, Integer> map = new HashMap<Double, Integer>(); double ratio = 0.0; int sameNum = 0; int localMax = 1; for (int j=i+1; j<points.length; j++) { if (points[j].x == points[i].x && points[j].y == points[i].y) { sameNum++; continue; } else if (points[j].x == points[i].x) { ratio = (double)Integer.MAX_VALUE; } else if (points[j].y == points[i].y) { ratio = 0.0; } else { ratio = (double)(points[j].y - points[i].y) / (double)(points[j].x - points[i].x); } if (map.containsKey(ratio)) { map.put(ratio, map.get(ratio)+1); } else { map.put(ratio, 2); } } for (int value : map.values()) { localMax = Math.max(localMax, value); } localMax = localMax + sameNum; allTimeMax = Math.max(allTimeMax, localMax); } return allTimeMax; } }
一些細節需要註意:第40-44行用一個localMax以及allTimeMax是有深意的,我開始的時候只維護一個allTimeMax,出錯了,不適用於input都是重復點這種情況【0,0】【0,0】這種情況。這種情況下map為空,sameNum為1。map.values()這個循環直接略過,如果只有一個allTimeMax將無法給它賦值
for (int num : map.values()) {
maxpts = Math.max(maxpts, num+dup);
}
Max Points on a line