Max Points on a Line - LeetCode
题目:Given n points on a 2D plane, find the maximum number of points that lie on the same straight line.
这道题一看就能知道大概要怎么做,先选中vector第一个点A,然后遍历剩下的点Xi,求出剩下每个点Xi与A之间的坐标差,这个坐标差的几何含义A到Xi的向量(当然如果不用坐标差,用斜率也是可以的,确实有人这么做而且通过了,但是用斜率的话又会出现小数,除以0这种很麻烦的问题),然后用一个vector存这个向量,另一个vector的对应位置存点的个数。一次遍历过后就可以把A扔掉了(因为经过A的所有直线在这次遍历中都计算过了),然后选择vector中第二个点B,继续上述过程,直到最后一个点。
但是这道题目难的地方在于需要考虑很多特殊情况,比如垂直(如果判断时用了斜率,那么垂直的情况要另外讨论),重合(解决重合就用一个overlap记录重合点的个数),溢出(如果判断的时候用了x1 * y2 == x2 * y1,那么碰到x1 = 65526, y2 = 65536就会出现整型溢出,就算转成浮点数还是有数据会让你溢出,亲测)。
打了几个小时,换了三四种方法,把各种坑都踩了一遍,还是有溢出的bug,于是参考了一下答案。。
一份答案用了求最大公约数的方法,这样就判断的时候就不用x1 * y2 == x2 * y1了,可以用x1/gcd1 == x2/gcd2 && y1/gcd1 == y2/gcd2来判断。
然后让我觉得自己蠢爆的一个地方是答案用了map<pair<int, int>, int> lines
,而我用了两个vector。其实一开是我也想用map的,但是map<Point, int>
会出错,貌似是因为Point不能直接比较大小,所以没法排序,另外Point也不能直接用==判断相等,所以没法用unordered_map(其实还是因为我懒得写重载)。
下面是我的丑陋的代码
#include <iostream>
#include <cstdlib>
#include <cmath>
#include <map>
#include <set>
#include <vector>
using namespace std;
class Solution {
public:
int maxPoints(vector<Point>& points) {
vector<Point> p;
vector<int> n;
int mmax = 0, m = 0, tmax = 0, overlap = 0;
if (points.size() != 0) {
mmax = 1;
}
for (int i = 0; i < points.size(); i++) {
tmax = 0;
overlap = 0;
for (int j = i+1; j < points.size(); j++) {
int a = points[j].x - points[i].x;
int b = points[j].y - points[i].y;
if (a == 0 && b == 0) {
overlap += 1;
} else {
int k;
int gcd = GCD(a,b);
if (gcd != 0) {
a /= gcd;
b /= gcd;
}
for(k = 0; k < p.size(); k++) {
if ((p[k]).x == a && (p[k]).y == b) {
n[k]++;
tmax = max(tmax, n[k]);
break;
}
}
if (k == p.size()) {
p.push_back(Point(a, b));
n.push_back(1);
if (tmax == 0) tmax++;
}
}
}
mmax = max(mmax, tmax+overlap+1);
p.clear();
n.clear();
}
return mmax;
}
int GCD(int a, int b) {
if (b == 0) return a;
else return GCD(b, a%b);
}
};
下面是别人的优美的代码
class Solution {
public:
int maxPoints(vector<Point> &points) {
if(points.size()<2) return points.size();
int result=0;
for(int i=0; i<points.size(); i++) {
map<pair<int, int>, int> lines;
int localmax=0, overlap=0, vertical=0;
for(int j=i+1; j<points.size(); j++) {
if(points[j].x==points[i].x && points[j].y==points[i].y) {
overlap++;
continue;
}
else if(points[j].x==points[i].x) vertical++;
else {
int a=points[j].x-points[i].x, b=points[j].y-points[i].y;
int gcd=GCD(a, b);
a/=gcd;
b/=gcd;
lines[make_pair(a, b)]++;
localmax=max(lines[make_pair(a, b)], localmax);
}
localmax=max(vertical, localmax);
}
result=max(result, localmax+overlap+1);
}
return result;
}
private:
int GCD(int a, int b) {
if(b==0) return a;
else return GCD(b, a%b);
}
};