https://leetcode-cn.com/problems/max-points-on-a-line/
给定一个二维平面,平面上有 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
方法一:设置两个标记位,斜率 k 与截距 b, 然后统计二者对应的个数。
但是这种方法存在两个问题:
class Solution {
public:
static bool cmp( vector<int> a, vector<int> b){
if( a[0] != b[0])
return a[0] < b[0];
return a[1] < b[1];
}
int countVertical( vector<vector<int>>& points){ //统计竖直方向上最多的点
int res = 1, count = 1;
for( int i = 1; i < points.size(); i++)
if( points[i-1][0] == points[i][0])
count++;
else
res = max( count, res), count = 1;
return max( count, res);
}
int maxPoints(vector<vector<int>>& points) {
if( points.empty()) return points.size();
//排序预处理
sort( points.begin(), points.end(), cmp);
int res = countVertical( points);
map< pair<int,int>,int> rec;
for( auto it:points)
rec[{it[0], it[1]}]++;
map< pair<long double,long double>, set<pair<int,int> > > record; //第一个是pair,里面为斜率和映射到y轴上的点,第二个是该直线对应的点
map< pair<long double,long double>, int > result;
for( int i = 0; i < points.size(); i++)
for( int j = i + 1; j < points.size(); j++)
if( points[j][0] != points[i][0]){ //不在同一条垂直线上时
long double k = (points[j][1] - points[i][1]) * 1.0 / (points[j][0] - points[i][0]);
long double b = points[j][1] - k * points[j][0];
if( record[{k,b}].find( {points[j][0], points[j][1]}) == record[{k,b}].end())
record[{k,b}].insert( {points[j][0], points[j][1]}), result[ {k,b}] += rec[ {points[j][0], points[j][1]}];
if( record[ {k, b}].find({ points[i][0], points[i][1]}) == record[{k,b}].end())
record[ {k, b}].insert({ points[i][0], points[i][1]}), result[ {k,b}] += rec[ {points[i][0], points[i][1]}];
}
//找出最多的个数
for( auto it:result)
if( res < it.second)
res = it.second;
return res;
}
};
上述的方法虽然 AC, 但是时间和空间都不尽人意。
方法二:优化上述方法,可以将其约分程成最简形式来统计斜率。
方法三:斜率换一种形式。例如将分数转化为乘法。