题 目 :
对于给定的n个位于同一二维平面上的点,求最多能有多少个点位于同一直线上
Given n points on a 2D plane, find the maximum number of points that lie on the same straight line.
分 析 :
分为n、n-1、n-2……3等组(每组分别包含n个点、n-1个点……),找到每组中包含第一个点的点数最多的直线(每个点与第一个点有一个斜率,通过斜率是否相等判断是否在同一条直线),则每组结果的最大值即为所求;
原 理 :
所求直线所包含的点,一定有一个最靠前的i点,使得直线上所有点为i~1的子集,所求值即为i组的结果
注 意 事 项 :
1、存在与第一个点相同的点;
2、使用浮点数不一定能准确的表示斜率,在此使用由String表示的分数来表示斜率
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
class Solution {
public int maxPoints(Point[] points) {
int result=0;
if(points.length<3) return points.length;
for(int i=0;i<points.length-1;i++){
HashMap map=new HashMap();
int maxNum=0,sameAsI=0;
for(int j=i+1;j<points.length;j++){
String key=xieLv(points[i],points[j]);
if(points[i].x==points[j].x&&points[i].y==points[j].y) {
sameAsI++;
continue;
}else {
map.put(key,map.containsKey(key) ? map.get(key)+1:1);
}
maxNum= Math.max(maxNum,map.get(key));
}
result=Math.max(result,maxNum+sameAsI);
}
return result+1;
}
private String xieLv(Point a,Point b){
int x=a.x-b.x,y=a.y-b.y;
if(x==0) return fuHao(x,y)+"ANY"+"/"+0;
else if(y==0) return fuHao(x,y)+0+"/"+"ANY";
int gcb=gcb(Math.abs(y),Math.abs(x));
return fuHao(x,y)+Math.abs(y)/gcb+"/"+Math.abs(x)/gcb;
}
private String fuHao(int x,int y){
if(x>=0&&y>=0||x<=0&&y<=0){
return "+";
}else return "-";
}
private int gcb(int a,int b){
if(b==0) return a;
else return gcb(b,a%b);
}
}
当然还有一种最简单直接的思路:
- 选择第一个点A1
- 选择第二个点A2, 和第一个点构成一条直线,
- 遍历剩下的n-2个点Ai, 判断Ai与A1构成的直线是否与A2与A1构成的直线保持一致,若是,则A1A2直线上的点数就+1;
- 每次求完A1A2直线上的最大点数, 和结果取最大值. 遍历结束就是结果
判断是否在一条直线上时, 注意有特殊情况. 并且斜率相等判断用乘法, 别用除法!
public class Solution {
public int maxPoints(Point[] points) {
if (null == points) {
return 0;
} else if (points.length < 3) {
return points.length;
}
int maxPoints = 2;
for (int i = 0; i < points.length; i++) {
int x1 = points[i].x;
int y1 = points[i].y;
for (int j = i + 1; j < points.length; j++) {
int x2 = points[j].x;
int y2 = points[j].y;
int max = 2;
for (int k = 0; k < points.length; k++) {
if (k == i || k == j) {
continue;
}
int x3 = points[k].x;
int y3 = points[k].y;
boolean flag;
if (x1 == x2) {
flag = x3 == x1;
} else if (y1 == y2) {
flag = y3 == y1;
} else {
flag = (y2 - y1) * (x3 - x1) == (y3 - y1) * (x2 -x1);
}
if (flag) {
max++;
}
}
maxPoints = Math.max(maxPoints, max);
}
}
return maxPoints;
}
}