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);
}
原文:http://www.cnblogs.com/apanda009/p/7932135.html