Given n points on a 2D plane, find the maximum number of points that lie on the same straight line.
/**
* Definition for a point.
* class Point {
* int x;
* int y;
* Point() { x = 0; y = 0; }
* Point(int a, int b) { x = a; y = b; }
* }
*/
//實現思想:從每一個點出發,固定起點,計算斜率相同的次數加上起點自身就是直線上的點
public class Solution {
public int maxPoints(Point[] points) {
//非空判斷
if(points==null||points.length==0)
{
return 0;
}
//只有一個或兩個節點 直接返回節點個數
if(points.length<=2)
{
return points.length;
}
int maxNumOfPoints=2;
//對比所有節點
for(int i=0;i<points.length;i++)
{
//此斜率上已有點的數量,不包括起點
HashMap<String,Integer> k_point=new HashMap<>();
//定義一些輔助結構
int vCnt=0;//垂直線上的點
int rCnt=1;//重合的點 自身已有一個
int hCnt=0;//水平的點
//記錄HashMap中的最大值 免去遍歷HashMap的過程
int mapMaxValue=0;
for(int j=i+1;j<points.length;j++)
{
int k_x=points[i].x-points[j].x;//x1-x2
int k_y=points[i].y-points[j].y;//y1-y2
//同爲零
if(k_x==0&&k_y==0)
{
rCnt++;//和起點重合的點多一個
}
else if(k_x==0)//斜率無窮大
{
vCnt++;//垂直線上的點
}
else if(k_y==0) //斜率爲零
{
hCnt++;//水平線上的點
}
else
{
//獲取此斜率的字符串表示形式
String k=getKReference(k_x,k_y);
int kValue=0;//本次放入的斜率的相同的點數量
//如果已經出現過此斜率 將出現次數加1
if(k_point.containsKey(k))
{
kValue=k_point.get(k)+1;
k_point.put(k,kValue);
//記錄Map中的最大值
}
//否則將此斜率表示加入Map中
else
{
k_point.put(k,1);
kValue=1;
}
if(mapMaxValue<kValue)
{
mapMaxValue=kValue;
}
}
}//從i出發的點遍歷完成 (內存for循環結束)
//比較一次出現最多的點
mapMaxValue=mapMaxValue>vCnt?mapMaxValue:vCnt;//斜率最大點和普通點
mapMaxValue=mapMaxValue>hCnt?mapMaxValue:hCnt;//斜率爲零的點和普通點
maxNumOfPoints=maxNumOfPoints>mapMaxValue+rCnt?maxNumOfPoints:mapMaxValue+rCnt;
}
return maxNumOfPoints;
}
/**********************
*獲取斜率的字符串表示形式
*實現思想爲將橫縱座標表示的最簡比值的形式
* 一正一負時,橫座標爲正
* 同爲負時 設置爲同爲正
**********************/
private String getKReference(int k_x,int k_y)
{
int x=Math.abs(k_x);
int y=Math.abs(k_y);
//比較大小
if(x<y)
{
int temp=x;
x=y;
y=temp;
}
int r=x%y;
while(r!=0)
{
x=y;
y=r;
r=x%y;
}
k_x/=y;
k_y/=y;
//避免異號
if(k_x*k_y<0)
{
if(k_x<0)
{
k_x=-k_x;
k_y=-k_y;
}
}
else if(k_x<0&&k_y<0)//同號均爲-時 設置爲正
{
k_x=-k_x;
k_y=-k_y;
}
return k_y+"/"+k_x;
}
}