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

NOTE: input types have been changed on April 15, 2019. Please reset to default code definition to get new method signature.

题解:

直接构造直线方程的话最后一个测试用例卡精度,可以选择变化率作为查找。

构造直线方程:

#define ERR 7e-14

class Solution {
public:
int judgeLine(double k, double b, int n, vector<vector<int>>& points) {
int cnt = 0;
for (int i = 0; i < n; i++) {
if (abs(k * (double)points[i][0] + b - (double)points[i][1]) < ERR) {
cnt++;
}
}
return cnt;
}
int getVert(int x, int n, vector<vector<int>>& points) {
int cnt = 0;
for (int i = 0; i < n; i++) {
if (points[i][0] == x) {
cnt++;
}
}
return cnt;
}
int maxPoints(vector<vector<int>>& points) {
int n = points.size(), res = 0;
if (n <= 2) {
return n;
}
for (int i = 0; i < n; i++) {
for (int j = i; j < n; j++) {
double k, b;
if (points[i][0] != points[j][0]) {
k = (double)((points[i][1] - points[j][1]) / (double)(points[i][0] - points[j][0]));
b = (double)points[i][1] - k * (double)points[i][0];
res = max(res, judgeLine(k, b, n, points));
}
else {
res = max(res, getVert(points[i][0], n, points));
}
}
}
return res;
}
};

 使用变化率:

class Solution {
public:
int getVert(int x, int n, vector<vector<int>>& points) {
int cnt = 0;
for (int i = 0; i < n; i++) {
if (points[i][0] == x) {
cnt++;
}
}
return cnt;
}
int getHori(int y, int n, vector<vector<int>>& points) {
int cnt = 0;
for (int i = 0; i < n; i++) {
if (points[i][1] == y) {
cnt++;
}
}
return cnt;
}
void symplify(int &a, int &b) {
int m = a, n = b, p = m % n;
while (p != 0) {
m = n;
n = p;
p = m % n;
}
if (n != 0) {
a /= n;
b /= n;
}
}
int maxPoints(vector<vector<int>>& points) {
int n = points.size(), res = 1;
if (n <= 2) {
return n;
}
map<vector<int>, int> dups;
for (int i = 0; i < n; i++) {
if (dups.find(points[i]) == dups.end()) {
for (int j = i + 1; j < n; j++) {
if (points[i] == points[j]) {
if (dups.find(points[i]) == dups.end()) {
dups.insert(make_pair(points[i], 1));
}
else {
dups[points[i]]++;
}
}
}
}
}
for (int i = 0; i < n; i++) {
int cnt = 0;
map<vector<int>, int> m;
vector<int> mkp;
mkp.push_back(points[i][0]);
mkp.push_back(points[i][1]);
int dup = 0;
int sum = 1;
if (dups.find(mkp) != dups.end()) {
dup = dups[mkp];
sum += dup;
}
for (int j = i + 1; j < n; j++) {
int a = points[i][0] - points[j][0];
int b = points[i][1] - points[j][1];
if (a == 0 && b != 0) {
sum = max(sum, getVert(points[i][0], n, points));
}
else if (b == 0 && a != 0) {
sum = max(sum, getHori(points[i][1], n, points));
}
else if (a != 0 && b != 0) {
symplify(a, b);
vector<int> idx;
idx.push_back(a);
idx.push_back(b);
if (m.find(idx) == m.end()) {
m.insert(make_pair(idx, 2));
}
else {
m[idx]++;
}
sum = max(sum, dup + m[idx]);
}
}
res = max(res, sum);
}
return res;
}
};