这道题看起来很简单,其实还是很有难度。说下心路历程。
我首先想到的是很多人都容易想到的算法没有往性能上考虑,用一个set集合先去重线段,然后再去看set集合里面每一条线段的点数。后来提交上去,执行时间超过1s了。于是改变了算法,在两次迭代的循环中直接计算每条线的点数,采用类似松弛的算法即给一个Map<String,Integer>
,存储直线和该条线上的点数。直接就能在两次迭代中搞定。但这只是大体的框架,里面还有诸多细节。
- 为什么要用
String
?
因为直线有两种情况(垂直,正常),得分开,String用来存储直线的唯一标识,这里取斜率。 - 不是还有个
y=kx+b
中的b吗?
这里在迭代循环中,每次都以一个点为起点,所以不会有平行的情况,即在二层循环中,k就能唯一标识一条直线。 - 里面还涉及到重复点的处理问题,具体请看代码
- 代码如下:
public static int maxPoints(Point[] points) {
int size = points.length;
int max = 0 ;
if(points.length == 1){
max = 1;
}else{
for(int i = 0; i < size; i++){
Map<String, Integer> maps = new HashMap<>();
int count = 0;
int dup = 0;
for(int j = 0; j < size; j++){
if(j != i){
int cTemp = 0;
int xi = points[i].x;
int yi = points[i].y;
int xj = points[j].x;
int yj = points[j].y;
int deltaY = yj - yi; //
int deltaX = xj - xi;
if(deltaY == 0&&deltaX == 0){
dup++;
count = dup + 1;
}else{
if(deltaX == 0){
String key = String.valueOf(xj + "v");
if(maps.get(key) != null){
cTemp = maps.get(key);
maps.put(key, ++cTemp);
}else{
cTemp = 2;
maps.put(key, cTemp);
}
//maps.put((double)xj, ++cTemp);
}else{
//只用判定斜率
double k = (double)deltaY / deltaX;
String key = String.valueOf(k + "n");
if(maps.get(key) != null){
cTemp = maps.get(key);
maps.put(key, ++cTemp);
}else{
cTemp = 2;
maps.put(key, cTemp);
}
// maps.put(k, cTemp);
}
if(count < cTemp + dup){
count = cTemp + dup;
}
}
}
}
if(max < count){
max = count;
}
}
}
return max;
网友评论