題 目 :
對於給定的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;
}
}