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;
}
}