题目
Given n points
on a 2D plane, find the maximum number of points that lie on the same straight line.
分析
这题没什么巧妙解法,就是枚举。遍历每一个点,统计其它点与该点构成直线的斜率相同的个数。
需要注意两点:
1. 重复出现的点要特殊处理。
2. 用float或double类型来计算斜率,虽然能通过LeetCode测试,但其实是错误的,浮点型存在精度丢失问题。为了保证精度,可以采用分数形式纪录斜率,为了保证斜率纪录结果的一致,利用最大公约数对斜率进行约分化为最简形式后保存即可,同时需要注意斜率的正、负、零等问题。
代码
import java.util.HashMap; import java.util.Map; public class MaxPointsOnALine { class Point { int x; int y; Point() { x = 0; y = 0; } Point(int a, int b) { x = a; y = b; } } private int gcd(int a, int b) { return b > 0 ? gcd(b, a % b) : a; } public int maxPoints(Point[] points) { int ret = 0; if (points == null) { return 0; } int N = points.length; if (N <= 2) { return N; } Map<String, Integer> records = new HashMap<String, Integer>(); for (int i = 0; i < N - 1; ++i) { int same = 1; int max = 0; records.clear(); for (int j = i + 1; j < N; ++j) { // keep x not negative int x, y = 0; if (points[i].x >= points[j].x) { x = points[i].x - points[j].x; y = points[i].y - points[j].y; } else { x = points[j].x - points[i].x; y = points[j].y - points[i].y; } int gcdXY = gcd(Math.abs(x), Math.abs(y)); if (gcdXY == 0) { // both x and y are zero // imply that points[i] and points[j] are equal ++same; } else { x /= gcdXY; y /= gcdXY; // record if (x == 0 || y == 0) { x = Math.abs(x); y = Math.abs(y); } String key = x + ":" + y; int value = 0; if (records.containsKey(key)) { value = records.get(key); } records.put(key, ++value); max = Math.max(max, value); } } ret = Math.max(ret, max + same); } return ret; } }