max-points-on-a-line
1.题干:
对于给定的n个位于同一二维平面上的点,求最多能有多少个点位于同一直线上
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) {
}
}
2.思路分析
最初的分析思路如下:
- 首先根据题干,可以提取出这几个关键字:二维平面,最多,同一直线
- 再观察给出的数据结构,包含两个变量x,y
- 由二维平面和数据结构中的变量可以抽象成一个坐标轴,x为横坐标,y为纵坐标
- 再根据同一直线和坐标轴可以联想到,确定两点在一条直线的方式为斜率k,只要斜率k相等两点便在一条直线上
思路中存在的问题:
- 在坐标轴中,垂直于x轴的线是没有斜率的(x/y)y为0,所以需要考虑到这一点
- 如果两个点重合,也需要考虑为共线
思路中可以继续改进的点:
- 判断分母为0,过于繁琐,我们应该想一个办法解决这个问题,让判断的等式变为一个乘法
进行简单的推导,过程如下:
通过这个推导,我们可以就可以忽略分母为0带来的影响了
最后的思路整理:
- 当传入数组长度小于3时,直接返回数组长度即可(两点一线,一个点,没有点)
- 这个算法考虑穷举法,首先在循环外部保存一个变量res,用于保存找到的结果,并且在每一轮循环中,与之比较
- 开始循环,由于上图中的推导过程涉及三个点,所以需要在最外层循环获得两个点,points[i]和points[i - 1],定义一个count保存当前可以共线的点数,通过这两个点计算出dx,dy,再保存一个点的x,y值,方便后面使用
- 首先判断,dx,dy是否全部都是0,如果全部都是0,则进行循环,判断points中的每个点是否与x,y相减都为0,若相等count++
- 否则,循环每个点,判断条件为(代入公式):(point.x - x) * dy = (point.y - y) * dx,若相等count++
- 最后在判断count和res的大小关系
3.代码实现
public int maxPoints(Point[] points) {
if (points.length < 3) {
return points.length;
}
int res = 0;
for (int i = 1; i < points.length; i++) {
int count = 0;
int x = points[i].x;
int y = points[i].y;
int dx = x - points[i - 1].x;
int dy = y - points[i - 1].y;
if (dx == 0 && dy == 0) {
for (int j = 0; j < points.length; j++) {
if (points[j].x == x && points[j].y == y) {
count++;
}
}
} else {
for (int j = 0; j < points.length; j++) {
if ((points[j].x - x)*dy == (points[j].y - y)*dx) {
count++;
}
}
}
res = Math.max(res, count);
}
return res;
}