给定一个二维平面,平面上有 n 个点,求最多有多少个点在同一条直线上。
示例 1:
输入: [[1,1],[2,2],[3,3]]
输出: 3
解释:
^
|
| o
| o
| o
+------------->
0 1 2 3 4
示例 2:
输入: [[1,1],[3,2],[5,3],[4,1],[2,3],[1,4]]
输出: 4
解释:
^
|
| o
| o o
| o
| o o
+------------------->
0 1 2 3 4 5 6
思路分析:一条直线可有一个点和斜率确定,然而斜率可能不是整数,所以对于斜率的处理保存很困难。
但是因为斜率是由Δy/Δx计算得到的,那么可以采用<Δx,Δy>到个数的映射,
不过需要将Δx,Δy化为最简的形式,这样,就可以将<Δx,Δy>这个数值对相等看成是斜率相等。
/**
* 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 a, int b)
{
if (b == 0)
return a;
else
return gcd(b, a % b);
}
int maxPoints(vector<Point>& points) {
int result = 0;
int pointsSize = points.size();
for (int i = 0; i < pointsSize; ++i) {
//固定points[i],遍历其他点,记录不同斜率个数,寻找斜率相同的直线中过点最多的
int tempRes = 0;//实时更新,当前直线中过点最多的
int samePointCnt = 0;//与points[i]重复的点个数
map<pair<int, int>, int> myMap;//<Δx,Δy>与其出现的次数关联
for (int j = i + 1; j < pointsSize; ++j) {
if (points[i].x == points[j].x && points[i].y == points[j].y) {//记录重合点
++samePointCnt;
}
else {
int xx = points[i].x - points[j].x;
int yy = points[i].y - points[j].y;
int maxDivisor = gcd(xx, yy);//计算最大公约数
xx /= maxDivisor;//化简
yy /= maxDivisor;
tempRes = max(tempRes, ++myMap[make_pair(xx, yy)]);
}
}
//tempRes + samePointCnt + 1这里需要加上重复的点、和自己
result = max(result, tempRes + samePointCnt + 1);
}
return result;
}
};