题目:
Given n points on a 2D plane, find the maximum number of points that lie on the same straight line.
Example 1:
Input: [[1,1],[2,2],[3,3]]
Output: 3
Explanation:
^
|
| o
| o
| o
+------------->
0 1 2 3 4
Example 2:
Input: [[1,1],[3,2],[5,3],[4,1],[2,3],[1,4]]
Output: 4
Explanation:
^
|
| o
| o o
| o
| o o
+------------------->
0 1 2 3 4 5 6
题目分析:给出二维平面上几个点坐标,求最多有几点共线。
方法一、
看了题目第一反应就是用斜率,固定一个点,求其余各点与该点组成的线的斜率。偷瞄了一眼这道题目的标签发现是hash,因此就考虑将斜率作为key,与这一点组成的线的斜率是key的点数为value(包含固定点),用这个hash表来快速统计结果。
然而由于存在与y轴平行的线,考虑用INT_MAX表示斜率。
在提交过程中发现了坑:
1、给出的点存在重复情况,重复的点也算作共线,因此还要统计重复情况。
2.
在提交中发现这样的错误,研究发现这个实例的斜率由于double的精度不够而错把这三个点看作同线。由于通过斜率来判断共线除法不可避免,因此必须使用别的方法。方法在后面介绍。
虽然没能通过这个实例,这里仍然给出这种方法的代码:
/**
* Definition for a point.
* struct Point {
* int x;
* int y;
* Point() : x(0), y(0) {}
* Point(int a, int b) : x(a), y(b) {}
* };
*/
class Solution {
public:
int maxPoints(vector<Point>& points) {
int n=points.size();
if(n==0) return 0;
if(n==1) return 1;
if(n==2) return 2;
int max=0;
for(int i=0;i<n-1;i++){
int imax=1;
map<float, int> hash_table;
int samepoint=0;
for(int j=i+1;j<n;j++){
if(points[j].x==points[i].x&&points[j].y==points[i].y) {
samepoint++;
continue;}
float k=0;
if(points[j].x-points[i].x!=0) k=float(points[j].y-points[i].y)/(points[j].x-points[i].x);
else k=INT_MAX;
if(hash_table[k]==0)
hash_table[k]=2;
else hash_table[k]++;
if(imax<hash_table[k]) imax=hash_table[k];
}
if(max<imax+samepoint) max=imax+samepoint;
}
return max;
}
};
方法二、
在斜率行不通的情况下我又看了大神们的解答,发现了利用最大公约数的方法。
把横纵坐标的值保存下来,不做除法,为了统一,我们把这两数分别除以它们的最大公约数,这样斜率相同的数就都会存到一个映射里面。
例如:[2,1],[4,2],[8,4]
4、2的最大公约数是2,8、4的最大公约数是4,对应的整数对都是2、1。
代码如下:
/**
* Definition for a point.
* struct Point {
* int x;
* int y;
* Point() : x(0), y(0) {}
* Point(int a, int b) : x(a), y(b) {}
* };
*/
class Solution {
public:
int gcd(int x, int y) {
return (y == 0) ? x : gcd(y, x % y);}
int maxPoints(vector<Point>& points) {
int n=points.size();
if(n==0) return 0;
if(n==1) return 1;
if(n==2) return 2;
int max=0;
for(int i=0;i<n-1;i++){
int imax=1;
map<pair<int,int>, int> hash_table;
int samepoint=0;int dx,dy;pair<int,int> k;
for(int j=i+1;j<n;j++){
if(points[j].x==points[i].x&&points[j].y==points[i].y) {
samepoint++;continue;}
dx = points[j].x - points[i].x;
dy = points[j].y - points[i].y;
int d = gcd(dx, dy);
k.first=dx/d;
k.second=dy/d;
if(hash_table[k]==0)
hash_table[k]=2;
else hash_table[k]++;
if(imax<hash_table[k]) imax=hash_table[k];
}
if(max<imax+samepoint) max=imax+samepoint;
}
return max;
}
};