Given n points on a 2D plane, find the maximum number of points that lie on the same straight line.
Example 1:
Input: [[1,1],[2,2],[3,3]] Output: 3 Explanation: ^ | | o | o | o +-------------> 0 1 2 3 4
Example 2:
Input: [[1,1],[3,2],[5,3],[4,1],[2,3],[1,4]] Output: 4 Explanation: ^ | | o | o o | o | o o +-------------------> 0 1 2 3 4 5 6
上面的暴力枚举法以“边”为中心,再看另一种暴力枚举法,以每个“点”为中心,然后 遍历剩余点,找到所有的斜率,如果斜率相同,那么一定共线对每个点,用一个哈希表,key为斜率,value为该直线上的点数,计算出哈希表后,取最大值,并更新全局最大值,最后就是结果。时间复杂度 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; }
* }
*/
class Solution {
public int maxPoints(Point[] points) {
int n = points.length;
if (n < 3) {
return n;
}
int res = 0;
for (int i = 0; i < n; i++) {
Map<Map<Integer, Integer>, Integer> hm = new HashMap<>();
int sameP = 1;
for (int j = i + 1; j < n; j++) {
int dx = points[i].x - points[j].x;
int dy = points[i].y - points[j].y;
if (dx == 0 && dy == 0) {
sameP++;
continue;
}
Map<Integer, Integer> tm = new HashMap<>();
int d = gcd(dx, dy);
tm.put(dx / d, dy / d);
hm.put(tm, hm.getOrDefault(tm, 0) + 1);
}
res = Math.max(res, sameP);
for (Map.Entry<Map<Integer, Integer>, Integer> e :
hm.entrySet()) {
res = Math.max(res, e.getValue() + sameP);
}
}
return res;
}
private int gcd(int a, int b) {
return b == 0 ? a : gcd(b, a % b);
}
}
一般来说判断三点共线有三种方法,斜率法,周长法,面积法(请参见这个帖子)。而其中通过判断叉积为零的面积法是坠好的。比如说有三个点A(x1, y1)、B(x2, y2)、C(x3, y3),那么判断三点共线就是判断下面这个等式是否成立:
判断 area(ABC) ==0
area(ABC) = 1/2 * ( AC X BC ) = 1/2 *((ax-cx)*(by-cy)-(bx-cx)*(ay-cy))
判断 (ax-cx)*(by-cy) == (bx-cx)*(ay-cy) 即可。
AC X BC 为两矢量的叉积
判断 area(ABC) ==0
area(ABC) = 1/2 * ( AC X BC ) = 1/2 *((ax-cx)*(by-cy)-(bx-cx)*(ay-cy))
判断 (ax-cx)*(by-cy) == (bx-cx)*(ay-cy) 即可。
AC X BC 为两矢量的叉积
/**
* Definition for a point.
* class Point {
* int x;
* int y;
* Point() { x = 0; y = 0; }
* Point(int a, int b) { x = a; y = b; }
* }
*/
class Solution {
public int maxPoints(Point[] points) {
int n = points.length;
if (n < 3) {
return n;
}
int res = 0;
for (int i = 0; i < n; i++) {
int sameP = 1;
for (int j = i + 1; j < n; j++) {
int cnt = 0;
long x1 = points[i].x, y1 = points[i].y;
long x2 = points[j].x, y2 = points[j].y;
if (x1 == x2 && y1 == y2) {
sameP++;
continue;
}
for (int k = 0; k < n; k++) {
long x3 = points[k].x, y3 = points[k].y;
if (x1 * y2 + x2 * y3 + x3 * y1 -
x1 * y3 - x2 * y1 - x3 * y2 == 0) {
cnt++;
}
}
res = Math.max(cnt, res);
}
res = Math.max(sameP, res);
}
return res;
}
}