给定一个二维平面,平面上有 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
这道题的可以采用点的轮询法。对于点A B C D E F,逐次以A作为起点开始查询有多少个点可以形成一条直线,最后代码类似于排序的冒泡法。
在这里采用一个映射队列 map<pair<int,int>,int> m 来存储数据。大体思想介绍完毕,下面说明一下要点:
【1】如何用 map 来存储直线?对于点(1, 2) (3, 4) (5,6),可以求两者的差值(dx, dy)为(2, 2) (4, 4),最大公约数为(2, 2) (4, 4),然后获取商,得到结果为(1, 1) (1, 1)
【2】如何求最大公约数?最大公约数的代码非常精简,需要说明,(dx, dy)形式下(-2,1)的最大公约数为 1,(-2,1)的最大公约数为 -1。
【3】如何处理重复的点?对于重复的点,我们用duplicate来记录,结果加上duplicate就可以
【4】如何计算单点?程序中特有 res = max(res, duplicate)来求单点时的结果
int gcd(int a,int b) { return b==0?a:gcd(b,a%b); //求a b的最大公约数 } //149 int maxPoints(vector<vector<int>>& points) { if(points.empty() || points[0].empty()) return 0; size_t num = points.size(); int res=0; for(size_t i=0;i<num;i++) { map<pair<int,int>,int> m; int duplicate=1; for(size_t j=i+1;j<num;j++) { if(points[i][0]==points[j][0] && points[i][1]==points[j][1]) {duplicate++;continue;} int dx = points[j][0] - points[i][0]; int dy = points[j][1] - points[i][1]; int g = gcd(dx,dy); m[pair<int,int>{dx/g,dy/g}]++; } res = max(res, duplicate); for(pair<pair<int,int>,int> a:m) res = max(res,a.second+duplicate); } return res; }//149