这道题的大致意思是给一堆点,然后找出一条线,使得这条线上的点数最多,返回最多的点数。显然这题的可能情况有很多,实在是不好处理,假如我们通过斜率进行计算的话还要保存考虑斜率不存在的情况,还有就是我们的点的坐标值是整数,但是计算斜率肯定要换成浮点数,不可避免的就会丢失经度。
参考了讨论区的解答,确实写得非常好,,,,学习一番
思路:
既然求斜率存在很多的问题,那么就转换一下思维,在斜率的时候免不了会分子与分母相除,这样就会出现浮点数,于是我们可以求出分子与分母的最大公约数进行约分。这样结束后的分子与分母同样是独特的。同样是可以代表一条直线的。
public int maxPoints(Point[] points) {
int result = 0;
if (points == null) {
return 0;
}
//假如是两个坐标相同的点也表示不同的点,假如是坐标不相同的点,那么两个定点确定一条直线
if (points.length <= 2) {
return points.length;
}
HashMap<Integer, HashMap<Integer, Integer>> map = new HashMap<>();
for (int i = 0; i < points.length; i++) {
Point a = points[i];
map.clear();
int counter = 0;
int max = 0;
for (int j = i + 1; j < points.length; j++) {
Point b = points[j];
int x = a.x - b.x;
int y = a.y - b.y;
//两个点的坐标相同
if (x == 0 && y == 0) {
counter++;
continue;
} else {
//计算最大公约数
int c = gcd(x, y);
//假如最大公约数存在
if (c != 0) {
x /= c;
y /= c;
}
//接下来就是看是不是在map中已经存在斜率相同的点了
if (map.containsKey(x)) {
if (map.get(x).containsKey(y)) {
map.get(x).put(y, map.get(x).get(y) + 1);
} else {
map.get(x).put(y, 1);
}
} else {
HashMap<Integer, Integer> mmap = new HashMap<>();
mmap.put(y, 1);
map.put(x, mmap);
}
max = Math.max(max, map.get(x).get(y));
}
}
result = Math.max(result, max + counter+1);
}
return result;
}
注意循环次数的减少,实际上一次遍历过后就能确定一个值了,因此每次都把map清空,而不是留在那里做最后的比较。每一个循环的结果是由两部份组成的max+counter,其中counter是代表的相同坐标点的情况。至于最后结果值加一是类似“两刀三段”的情况。我们求得是段,而我们一直在计算的是刀。