Leetcode No.149 ***

给定一个二维平面,平面上有 个点,求最多有多少个点在同一条直线上。

示例 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

 

 
 
 
 
 
posted @ 2019-05-17 16:41  andyalgorithm  阅读(111)  评论(0编辑  收藏  举报