题目
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;
}
}