Given n points on a 2D plane, find the maximum number of points that lie on the same straight line.
析:此处的在一条直线上也包含斜的直线,因此分为水平竖直线、斜线两种情况。
如果是水平竖直线,直接以横坐标或纵坐标为参考作统计即可;
如果是斜线,得先把斜线定义成Line类,包含k b两个值,
之后分别统计每条斜线上的点的个数。
斜线那个方法的复杂度为o(n*n),因为创建斜线时需要双层循环。
自定义的类加上equals和hashCode方法
import java.util.*;
public class Main {
public static void main(String[] args){
Scanner sc= new Scanner(System.in);
Main main = new Main();
Point[] points =new Point[4];
points[0]= new Point(3,10);
points[1]= new Point(0,2);
points[2]= new Point(0,2);
points[3]= new Point(3,10);
System.out.println(main.maxPoints(points));
}
public int maxPoints(Point[] points) {
if(points==null || points.length==0)
return 0;
if(points.length==1)
return 1;
return Math.max(maxPoints1(points),maxPoints2(points));
}
// 考虑在水平线或竖直线
public int maxPoints1(Point[] points) {
// map为 <x或y的值,出现点的次数>
Map<Integer,Integer> mapx = new HashMap<>();
Map<Integer,Integer> mapy = new HashMap<>();
for(Point p:points){
if(!mapx.containsKey(p.x))
mapx.put(p.x,1);
else
mapx.put(p.x, mapx.get(p.x)+1);
if(!mapy.containsKey(p.y))
mapy.put(p.y,1);
else
mapy.put(p.y, mapy.get(p.y)+1);
}
int max=0;
for(Integer t:mapx.keySet()){
max = max>mapx.get(t)?max:mapx.get(t);
}
for(Integer t:mapy.keySet()){
max = max>mapy.get(t)?max:mapy.get(t);
}
return max;
}
// 考虑斜线
public int maxPoints2(Point[] points) {
Set<Line> lineSet = new HashSet<>();
// <直线,直线上点的个数>
Map<Line,Integer> map = new HashMap<>();
for(int i=0;i<points.length;i++)
for(int j=i+1;j<points.length;j++){
Point p1 = points[i];
Point p2 = points[j];
if(p1.x!=p2.x && p1.y!=p2.y){
double k=(p1.y-p2.y)*1.0/(p1.x-p2.x);
double b= p1.y-k*p1.x;
Line line = new Line(k,b);
lineSet.add(line);
}
}
for(Point p:points){
for(Line line:lineSet){
// 如果点在直线上
if (Math.abs(p.y-line.k*p.x-line.b)<1e-9){
if(map.containsKey(line))
map.put(line,map.get(line)+1);
else
map.put(line,1);
}
}
}
int res=0;
for(Line l:map.keySet()){
res=res>map.get(l)?res:map.get(l);
}
return res;
}
}
class Point {
int x,y;
public Point(){
}
public Point(int x, int y) {
this.x = x;
this.y = y;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Point point = (Point) o;
if (x != point.x) return false;
return y == point.y;
}
@Override
public int hashCode() {
int result = x;
result = 31 * result + y;
return result;
}
}
class Line{
double k,b;
public Line(double k, double b) {
this.k = k;
this.b = b;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Line line = (Line) o;
if (Double.compare(line.k, k) != 0) return false;
return Double.compare(line.b, b) == 0;
}
@Override
public int hashCode() {
int result;
long temp;
temp = Double.doubleToLongBits(k);
result = (int) (temp ^ (temp >>> 32));
temp = Double.doubleToLongBits(b);
result = 31 * result + (int) (temp ^ (temp >>> 32));
return result;
}
}