Hard
今天上午有幸参加了Refdash的免费Mock interview, 被暴击一万点.不过先刷完L家tag题再说那道题吧.
这也是一道逻辑其实很简单,但是很多细节容易出错的题.
要找到共线最多的点,我们主线是通过找斜率. 遍历每个点和它后面的点,找到俩俩斜率,构建一个以斜率为key, 斜率出现的次数为value的hashMap. 我们用String来存斜率,要将dx, dy处理到lowest term, 通过除以他们的最大公约数来做到. 这里求gcd的算法叫做Euclidean算法,具体见链接,比较简单好用. 注意我们处理跟points[i]重合的点的方法是统计samePoint这个变量. 如果遇到i之后有相同的点就累加. 首先我们有一个总的res来统计当前共线最多的点,然后每遍历一个点和其后面的点时(即每次进入外层for循环)都再记录一个max来记录这个点能跟后面的点组成共线点最多的那条直线上的点数. 每走一遍内循环,就是遍历到这个点后面的某个点,就用这个斜率下的频数和当前max的中的最大值来更新max. 每次遍历完某个点之后所有的点(即内循环遍历完),则更新一下总的res为Math.max(res, max). 同时注意一下,每一次外循环换一个点,map要全部清除之前的记录。因为我们要找的是从这个点出发的共线的最多点,不能要之前的mapping, 只需要之前的res拿来更新就可以.
/**
* 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) {
if (points == null || points.length == 0){
return 0;
}
Map<String, Integer> map = new HashMap<>();
int res = 0;
for (int i = 0; i < points.length; i++){
map.clear();
int samePoint = 1;
int max = 0;
for (int j = i + 1; j < points.length; j++){
int dx = points[j].x - points[i].x;
int dy = points[j].y - points[i].y;
if (dx == 0 && dy == 0){
samePoint++;
continue;
}
int gcd = generateGCD(dx, dy);
dx /= gcd;
dy /= gcd;
String slope = dy + "/" + dx;
if (map.containsKey(slope)){
map.put(slope, map.get(slope) + 1);
} else {
map.put(slope, 1);
}
max = Math.max(max, map.get(slope));
}
res = Math.max(res, max + samePoint);
}
return res;
}
private int generateGCD(int a, int b){
if (b == 0){
return a;
} else {
return generateGCD(b, a % b);
}
}
}