题目地址:
https://leetcode.com/problems/max-points-on-a-line/
给定 n n n个二维平面里点的坐标,问最多有多少个点在同一条直线上。
暴力 O ( n 3 ) O(n^3) O(n3)方法可以参考https://blog.youkuaiyun.com/qq_46105170/article/details/112556694。下面介绍一个 O ( n 2 ) O(n^2) O(n2)做法。
可以枚举直线上的一个点
c
c
c,然后看对于每个斜率,别的其他点有多少个share相同的斜率。对于斜率,可以分三种情况:
1、对于与
c
c
c重合的点,要开一个变量专门存储;
2、对于斜率是无穷大的点,也要开一个变量专门存储;
3、对于别的情况,则开一个哈希表,key存斜率,value存过
c
c
c且斜率与key相等的点的个数,其中为了精确,斜率我们存分数的分子和分母,并将其标准化一下,比如要求分子分母互素,并且分子一定要非负(如果分子是
0
0
0,则要求分母必须是正数),这样保证分数表示的唯一性。
代码如下:
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
public class Solution {
class Slope {
// 斜率是n / m
int n, m;
public Slope(int x, int y) {
n = x;
m = y;
int gcd = gcd(n, m);
n /= gcd;
m /= gcd;
if (n == 0) {
m = Math.abs(m);
} else if (n < 0) {
n = -n;
m = -m;
}
}
// 求一下x和y的最大公约数
private int gcd(int x, int y) {
while (y != 0) {
int tmp = y;
y = x % y;
x = tmp;
}
return Math.abs(x);
}
@Override
public boolean equals(Object o) {
Slope slope = (Slope) o;
return n == slope.n && m == slope.m;
}
@Override
public int hashCode() {
return Objects.hash(n, m);
}
}
public int maxPoints(int[][] points) {
if (points == null || points.length == 0) {
return 0;
}
int res = 0;
Map<Slope, Integer> map = new HashMap<>();
for (int i = 0; i < points.length; i++) {
// 遇到与之前的点重合的点则略过
if (i > 0 && Arrays.equals(points[i], points[i - 1])) {
continue;
}
// dup记录与points[i]重合的点的个数,vert记录与point[i]不重合并且斜率是正无穷的点的个数
int dup = 0, vert = 0;
for (int j = i + 1; j < points.length; j++) {
// 如果重合则dup累加,如果斜率是正无穷则vert累加
if (Arrays.equals(points[i], points[j])) {
dup++;
} else if (points[j][0] == points[i][0]) {
vert++;
} else {
// 否则说明在当前斜率下,找到了一个点
Slope slope = new Slope(points[j][1] - points[i][1], points[j][0] - points[i][0]);
map.put(slope, map.getOrDefault(slope, 0) + 1);
}
}
// 首先以与points[i]在同一条垂直线的点的总数更新答案
res = Math.max(res, dup + 1 + vert);
// 然后以非无穷大的斜率对应的点的个数更新答案
for (Map.Entry<Slope, Integer> entry : map.entrySet()) {
res = Math.max(res, dup + 1 + entry.getValue());
}
// 别忘了清空哈希表
map.clear();
}
return res;
}
}
时空复杂度 O ( n 2 ) O(n^2) O(n2)。