题目描述:
Given n points on a 2D plane, find the maximum number of points that lie on the same straight line.
给n个点,看最多多少个点在同一条线。
我真的服了自己,一开始想那么麻烦,还去求y=kx+b。最后还有问题,因为当k失去精度后,b的计算可能不相等。
下面是一段非常复杂的计算,还没有成功,就当复习了hashcode和equals用法!
这里将所有的直线全部计算出来,包括水平线,竖直线,以及各种不同的k,b组成的线。太麻烦了!!!
这个题还有一点就是所给的点可能有重复的,这个地方要处理好。
class Point {
int x;
int y;
Point() { x = 0; y = 0; }
Point(int a, int b) {
x = a; y = b;
}
}
class Line{
double k;
double b;
Line(){
k = 0; b = 0;
}
Line(double k, double b) {
this.k = k; this.b = b;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
long temp;
temp = Double.doubleToLongBits(b);
result = prime * result + (int) (temp ^ (temp >>> 32));
temp = Double.doubleToLongBits(k);
result = prime * result + (int) (temp ^ (temp >>> 32));
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Line other = (Line) obj;
if (Double.doubleToLongBits(b) != Double.doubleToLongBits(other.b))
return false;
if (Double.doubleToLongBits(k) != Double.doubleToLongBits(other.k))
return false;
return true;
}
}
public class Solution149 {
public int maxPoints(Point[] points) {
if(points.length==1||points.length==2)
return points.length;
int kind=1,sum=1;
for(int i=1;i<points.length;i++){
if(points[i].x==points[0].x&&points[i].y==points[0].y)
sum++;
else{
kind++;
break;
}
}
if(kind==1)
return sum;
int maxpoint=0,n=points.length;
Map<Integer, Integer> horizenMap=new HashMap<Integer, Integer>();
Map<Integer, Integer> verticalMap=new HashMap<Integer, Integer>();
Map<Line, Integer> lineMap=new HashMap<Line, Integer>();
for(int i=0;i<n;i++){
boolean horizenflag=true;
boolean verticalflag=true;
Set<Double> kSet=new HashSet<Double>();
for(int j=0;j<n;j++){
if(i==j||(points[i].y==points[j].y&&points[i].x==points[j].x))
continue;
if(points[i].x==points[j].x&&points[i].y!=points[j].y){
if(verticalflag){
if(!verticalMap.containsKey(points[i].x))
verticalMap.put(points[i].x,1);
else
verticalMap.put(points[i].x,verticalMap.get(points[i].x)+1);
verticalflag=false;
}
}
else if(points[i].y==points[j].y&&points[i].x!=points[j].x){
if(horizenflag){
if(!horizenMap.containsKey(points[i].y))
horizenMap.put(points[i].y,1);
else
horizenMap.put(points[i].y,horizenMap.get(points[i].y)+1);
horizenflag=false;
}
}else{
double k=1.0 * (points[i].y - points[j].y) / (points[i].x - points[j].x);
double b=points[j].y-k*points[j].x;
if(!kSet.contains(k)){
Line line=new Line(k, b);
if(!lineMap.containsKey(line))
lineMap.put(line, 1);
else
lineMap.put(line, lineMap.get(line)+1);
kSet.add(k);
}
}
}
}
for(Integer key:horizenMap.keySet())
maxpoint=horizenMap.get(key)>maxpoint?horizenMap.get(key):maxpoint;
for(Integer key:verticalMap.keySet())
maxpoint=verticalMap.get(key)>maxpoint?verticalMap.get(key):maxpoint;
for(Line key:lineMap.keySet())
maxpoint=lineMap.get(key)>maxpoint?lineMap.get(key):maxpoint;
return maxpoint;
}
}
后来想起来每次经过一个点,就将这个点能够经过的所有直线所包含最多的点算出来就行了!!
写了下面一段代码,AC了,思路清晰就能节约很长时间,所以一定要想清楚再动手才能提高效率!
public class Solution {
public int maxPoints(Point[] points) {
if(points.length<3)
return points.length;
int maxpoint=0,n=points.length;
int result=0;
Map<Double, Integer> lineMap=new HashMap<Double, Integer>();
for(int i=0;i<n;i++){
maxpoint=0;lineMap.clear();
int horizenNum=0,verticalNum=0;
int dumplicate=0;
for(int j=0;j<n;j++){
if(i==j||(points[i].y==points[j].y&&points[i].x==points[j].x))
dumplicate++;
else if(points[i].x==points[j].x&&points[i].y!=points[j].y)
verticalNum++;
else if(points[i].y==points[j].y&&points[i].x!=points[j].x)
horizenNum++;
else{
double k=1.0 * (points[i].y - points[j].y) / (points[i].x - points[j].x);
if(!lineMap.containsKey(k))
lineMap.put(k,1);
else
lineMap.put(k,lineMap.get(k)+1);
}
}
horizenNum+=dumplicate;
verticalNum+=dumplicate;
maxpoint=horizenNum>verticalNum?horizenNum:verticalNum;
for(Double key:lineMap.keySet())
maxpoint=lineMap.get(key)+dumplicate>maxpoint?lineMap.get(key)+dumplicate:maxpoint;
result=maxpoint>result?maxpoint:result;
}
return result;
}
}