zoukankan      html  css  js  c++  java
  • No.149 Max Point on a Line

    No.149 Max Point on a Line

    Given n points on a 2D plane, find the maximum number of points that lie on the same straight line.

    尝试1:考虑不周,一条直线上的点会重复计数,但没找到解决方法【wrong】

    Input: [[0,0],[-1,-1],[2,2]]
    Output: 4
    Expected: 3

     1 /**
     2  * Definition for a point.
     3  * struct Point {
     4  *     int x;
     5  *     int y;
     6  *     Point() : x(0), y(0) {}
     7  *     Point(int a, int b) : x(a), y(b) {}
     8  * };
     9  */
    10 class Solution 
    11 {
    12 public:
    13     int maxPoints(vector<Point>& points)
    14     {
    15      //输入:二维平面上的一组点
    16      //输出:同一条直线上的点的最大数量
    17      //思路:两层循环,依次找出每两个点组成的直线的斜率slope,O(n2)本以为很大,还好,相信自己
    18      //         将得到的数据存到map中:key为斜率,value为该斜率的点的个数
    19         int count = points.size() ;
    20         if( count == 0)
    21             return 0;
    22         if( count == 1)
    23             return 1;
    24         if( count == 2)
    25             return 2;
    26         
    27         map<double, int> result;
    28         double slope;
    29         for(int i=0; i< count ; i++)
    30             for(int j = i+1; j<count; j++)
    31             {
    32                 if(points[i].x == points[j].x)
    33                     slope = numeric_limits<double>::max();
    34                 else
    35                     slope = (points[i]. y - points[j]. y)/(points[i]. x - points[j]. x);//除法!!分母
    36                 if(result.find(slope) == result.end())
    37                     result[slope] = 2;
    38                 else
    39                     result[slope]++;
    40             }
    41         
    42         int max = 0;
    43         for(auto const i : result)
    44         {
    45             if(i.second > max)
    46                 max = i.second;
    47         }
    48         return max;
    49     }
    50 
    51 };
    View Code

    尝试2:【几次提交,总是有点小问题】

    输入:二维平面上的一组点
    输出:同一条直线上的点的最大数量
    思路:两层循环,依次找出每两个点组成的直线的斜率slope,O(n2)本以为很大,还好,相信自己
              将得到的数据存到map中:key为斜率,value为该斜率的点的索引的集合【可以去重】

     1 /**
     2  * Definition for a point.
     3  * struct Point {
     4  *     int x;
     5  *     int y;
     6  *     Point() : x(0), y(0) {}
     7  *     Point(int a, int b) : x(a), y(b) {}
     8  * };
     9  */
    10 class Solution
    11 {
    12 public:
    13     int maxPoints(vector<Point> &points)
    14     {//输入:二维平面上的一组点
    15      //输出:同一条直线上的点的最大数量
    16      //思路:两层循环,依次找出每两个点组成的直线的斜率slope,O(n2)本以为很大,还好,相信自己
    17      //         将得到的数据存到map中:key为斜率,value为该斜率的点的索引的集合
    18         //const double INFINITY = numeric_limits<double>::max();//无穷大斜率,即与y轴平行!!!//leetcode不支持
    19         //用INT_MAX
    20         int count = points.size() ;
    21         if(count < 3)
    22             return count;
    23         map<double, set<int>> result;
    24         double slope;
    25         int max = 0;
    26         int SamePointCount = 0;//记录与当前定点i重合的点的数量(不包括i)
    27         for(int i=0; i< count; i++)
    28         {
    29             result.clear();
    30             SamePointCount = 0;
    31             for(int j = 0; j<count; j++)
    32             {
    33                 if(i==j)
    34                     continue;
    35                 if(points[i].x == points[j].x && points[i].y == points[j].y)
    36                 {
    37                     SamePointCount++;
    38                     continue;
    39                 }
    40                 if(points[i].x == points[j].x)
    41                     slope = INT_MAX;
    42                     //此时,即使斜率相同,也不在同一条直线上,还与x(截距)有关
    43                 else
    44                     slope = (double)(points[i]. y - points[j]. y)/(double)(points[i]. x - points[j]. x);//除法!!分母
    45                     //精度问题导致错误!!!
    46                 result[slope].insert(i);
    47                 result[slope].insert(j);//set重复插入会无视                
    48             }
    49             for(auto const &i : result)
    50             {
    51                 if(i.second.size()+SamePointCount > max)
    52                     max = i.second.size()+SamePointCount;
    53             }
    54         
    55         }
    56             return max;
    57     }
    58 };
    View Code

    最终:

      之前的想法与思路都是有问题的,最开始想到的,是统计每两个点确定的斜率,用哈希表来保存;之后发现,在统计斜率的时候,会有点被重复计算,就想到用一个set来保存同一斜率的点的集合;再提交,又出现问题,以为是无穷斜率需要考虑截距,其实,其他的都需要,就想,难道,要以斜率和截距来确定一条直线再统计??!!太麻烦了。

      之后,参考网上其他人的做法,找到一种比较好的做法:

      任意一条直线都可以表述为:y = ax + b
      假设,有两个点(x1,y1), (x2,y2),如果它们都在这条直线上,则有y1 = kx1 +b;y2 = kx2 +b
      由此可以得到关系,k = (y2-y1)/(x2-x1)。即如果点c和点a的斜率为k, 而点b和点a的斜率也为k,可以知道点c和点b也在一条线上。

      关键在于要有一个定点:
      取定一个点points[i], 遍历其他所有节点, 然后统计斜率相同的点数,并求取最大值即可。

      【该遍历要遍历所有,不是从i+1开始】

      注意事项:

        1、在编程过程中,若不需要,就不要存储过程或其他结果,浪费空间和时间

        2、各种测试用例的思考,多考虑,因为这个,提交好多次;要自己去想,做调试,不要等提交后,再。。

        3、修改之后,一定要做回归测试!!!

        4、特殊情况:

        1. 重复点【不要当成斜率无穷大】      
        2. 涉及除法,分母为0,斜率无穷大的情况,即与y轴平行
        3. 只有相同的点,此时直接返回即可
        4. 计算精度问题

    最终版本:

      1 #include "stdafx.h"
      2 #include <vector>
      3 #include <map>
      4 #include <time.h>
      5 #include <iostream>
      6 #include <limits>
      7 #include <set>
      8 using namespace std;
      9 
     10 struct Point
     11 {
     12     int x;
     13     int y;
     14     Point(): x(0),y(0) {}
     15     Point(int a, int b) : x(a),y(b) {}
     16 };
     17 class Solution
     18 {
     19 public:
     20     int maxPoints(vector<Point> &points)
     21     {//输入:二维平面上的一组点
     22      //输出:同一条直线上的点的最大数量
     23      //思路:两层循环,依次找出每两个点组成的直线的斜率slope,O(n2)本以为很大,还好,相信自己
     24      //         将得到的数据存到map中:key为斜率,value为该斜率的点的索引的集合
     25 //        const double INFINITY = numeric_limits<double>::max();//无穷大斜率,即与y轴平行
     26         //leetcode不支持
     27         int count = points.size() ;
     28         if(count < 3)
     29             return count;
     30     
     31         map<double, int> result;
     32         double slope;
     33         int max = 0;
     34         int SamePointCount = 0;//记录与当前定点i重合的点的数量(不包括i)
     35         for(int i=0; i< count; i++)
     36         {
     37             result.clear();
     38             SamePointCount = 0;
     39             for(int j = 0; j<count; j++)//
     40             {
     41                 if(i==j)//跳过相同的点
     42                     continue;
     43                 if(points[i].x == points[j].x && points[i].y == points[j].y)
     44                 {
     45                     SamePointCount++;
     46                     continue;
     47                 }
     48                 if(points[i].x == points[j].x)
     49                     slope = INT_MAX;
     50                     //此时,即使斜率相同,也不在同一条直线上,还与x(截距)有关
     51                 else
     52                     slope = (double)(points[i]. y - points[j]. y)/(double)(points[i]. x - points[j]. x);//除法!!分母
     53                     //精度问题导致错误!!!
     54                 if(result.find(slope) == result.end())
     55                     result[slope]=2;//包括该定点
     56                 else
     57                     result[slope]++;            
     58             }
     59             if(result.size() == 0)//极端:只有重复点!!!
     60                 return SamePointCount+1;
     61 
     62             for(auto const &i : result)
     63             {
     64                 if(i.second+SamePointCount > max)
     65                     max = i.second+SamePointCount;
     66             }
     67         
     68         }
     69             return max;
     70     }
     71 
     72     void generatePoints(int n , vector<Point> &points)
     73     {
     74         srand(time(0));
     75         Point p;
     76         for(int i=0; i<n; i++)
     77         {
     78             p.x = rand();
     79             p.y = rand();
     80             points.push_back(p);
     81         }
     82     }
     83 };
     84 
     85 int main()
     86 {
     87     Solution sol;
     88     vector<Point> points;
     89 //    sol.generatePoints(6,points);
     90 /*
     91     points.push_back(Point());//点(0,0)
     92     points.push_back(Point(-1,-1));//点(-1,-1)
     93     points.push_back(Point(2,2));//点(2,2)
     94     //输出应为3,却输出4,有点重复计算了!
     95 */
     96 /*
     97     //测试用例:输出应为25
     98     Point test[]= {Point(40,-23),Point(9,138),Point(429,115),Point(50,-17),Point(-3,80), Point(-10,33), Point(5,-21), Point(-3,80), Point(-6,-65), Point(-18,26), Point(-6,-65), Point(5,72), Point(0,77), Point(-9,86), Point(10,-2), Point(-8,85), Point(21,130), Point(18,-6), Point(-18,26), Point(-1,-15), Point(10,-2), Point(8,69), Point(-4,63), Point(0,3), Point(-4,40), Point(-7,84), Point(-8,7), Point(30,154), Point(16,-5), Point(6,90), Point(18,-6), Point(5,77), Point(-4,77), Point(7,-13), Point(-1,-45), Point(16,-5), Point(-9,86), Point(-16,11), Point(-7,84), Point(1,76), Point(3,77), Point(10,67), Point(1,-37), Point(-10,-81), Point(4,-11), Point(-20,13), Point(-10,77), Point(6,-17), Point(-27,2), Point(-10,-81), Point(10,-1), Point(-9,1), Point(-8,43), Point(2,2), Point(2,-21), Point(3,82), Point(8,-1), Point(10,-1), Point(-9,1), Point(-12,42), Point(16,-5), Point(-5,-61), Point(20,-7), Point(9,-35), Point(10,6), Point(12,106), Point(5,-21), Point(-5,82), Point(6,71), Point(-15,34), Point(-10,87), Point(-14,-12), Point(12,106), Point(-5,82), Point(-46,-45), Point(-4,63), Point(16,-5), Point(4,1), Point(-3,-53), Point(0,-17), Point(9,98), Point(-18,26), Point(-9,86), Point(2,77), Point(-2,-49), Point(1,76), Point(-3,-38), Point(-8,7), Point(-17,-37), Point(5,72), Point(10,-37), Point(-4,-57), Point(-3,-53), Point(3,74), Point(-3,-11), Point(-8,7), Point(1,88), Point(-12,42), Point(1,-37), Point(2,77), Point(-6,77), Point(5,72), Point(-4,-57), Point(-18,-33), Point(-12,42), Point(-9,86), Point(2,77), Point(-8,77), Point(-3,77), Point(9,-42), Point(16,41), Point(-29,-37), Point(0,-41), Point(-21,18), Point(-27,-34), Point(0,77), Point(3,74), Point(-7,-69), Point(-21,18), Point(27,146), Point(-20,13), Point(21,130), Point(-6,-65), Point(14,-4), Point(0,3), Point(9,-5), Point(6,-29), Point(-2,73), Point(-1,-15), Point(1,76), Point(-4,77), Point(6,-29)};
     99     vector<Point> points(test,test+sizeof(test)/sizeof(Point));
    100     */
    101 /*
    102     points.push_back(Point(2,2));//
    103     points.push_back(Point(2,2));//
    104     points.push_back(Point(2,2));//
    105 */
    106 ///*
    107     //测试用例:重复点问题,accept=4
    108     points.push_back(Point(1,1));//0
    109     points.push_back(Point(1,1));//1
    110     points.push_back(Point(2,2));//2
    111     points.push_back(Point(2,2));//3
    112 //*/
    113 
    114 /*
    115     //测试用例:输出应为6
    116     points.push_back(Point(0,-12));//0
    117     points.push_back(Point(5,2));//1
    118     points.push_back(Point(2,5));//2
    119     points.push_back(Point(0,-5));//3
    120     points.push_back(Point(1,5));//4
    121     points.push_back(Point(2,-2));//5
    122     points.push_back(Point(5,-4));//6
    123     points.push_back(Point(3,4));//7
    124     points.push_back(Point(-2,4));//8
    125     points.push_back(Point(-1,4));//9
    126     points.push_back(Point(0,-5));//10
    127     points.push_back(Point(0,-8));//11
    128     points.push_back(Point(-2,-1));//12
    129     points.push_back(Point(0,-11));//13
    130     points.push_back(Point(0,-9));//14
    131 */
    132 
    133     for(auto const &i : points)
    134         cout << i.x << " "<<i.y<<endl;
    135     cout << sol.maxPoints(points)<<endl;
    136     return 0;
    137 }

     最终不简洁版本:

      1 #include "stdafx.h"
      2 #include <vector>
      3 #include <map>
      4 #include <time.h>
      5 #include <iostream>
      6 #include <limits>
      7 #include <set>
      8 using namespace std;
      9 
     10 struct Point
     11 {
     12     int x;
     13     int y;
     14     Point(): x(0),y(0) {}
     15     Point(int a, int b) : x(a),y(b) {}
     16 };
     17 class Solution
     18 {
     19 public:
     20     int maxPoints(vector<Point> &points)
     21     {//输入:二维平面上的一组点
     22      //输出:同一条直线上的点的最大数量
     23      //思路:两层循环,依次找出每两个点组成的直线的斜率slope,O(n2)本以为很大,还好,相信自己
     24      //         将得到的数据存到map中:key为斜率,value为该斜率的点的索引的集合
     25 //        const double INFINITY = numeric_limits<double>::max();//无穷大斜率,即与y轴平行
     26         int count = points.size() ;
     27         if(count < 3)
     28             return count;
     29 /*
     30         if( count == 0)
     31             return 0;
     32         if( count == 1)
     33             return 1;
     34         if( count == 2)
     35             return 2;
     36 */        
     37         map<double, int> result;
     38         double slope;
     39         int max = 0;
     40         int SamePointCount = 0;//记录与当前定点i重合的点的数量(不包括i)
     41         for(int i=0; i< count; i++)
     42         {
     43             result.clear();
     44             SamePointCount = 0;
     45             for(int j = 0; j<count; j++)//
     46             {
     47                 if(i==j)//跳过相同的点
     48                     continue;
     49                 if(points[i].x == points[j].x && points[i].y == points[j].y)
     50                 {
     51                     SamePointCount++;
     52                     continue;
     53                 }
     54                 if(points[i].x == points[j].x)
     55                     slope = INT_MAX;
     56                     //此时,即使斜率相同,也不在同一条直线上,还与x(截距)有关
     57                 else
     58                     slope = (double)(points[i]. y - points[j]. y)/(double)(points[i]. x - points[j]. x);//除法!!分母
     59                     //精度问题导致错误!!!
     60                 if(result.find(slope) == result.end())
     61                     result[slope]=2;//包括该定点
     62                 else
     63                     result[slope]++;            
     64             }
     65             if(result.size() == 0)//极端:只有重复点
     66                 return SamePointCount+1;
     67 
     68             for(auto const &i : result)
     69             {
     70                 if(i.second+SamePointCount > max)
     71                     max = i.second+SamePointCount;
     72             }
     73         
     74         }
     75             return max;
     76 /*
     77         int max = 0;
     78         for(auto const i : result)
     79         {
     80             if(i.first != INFINITY && i.second.size() > max)
     81                 //斜率无穷大即与y轴垂直的,要单独计算
     82                 max = i.second.size();
     83         }
     84         if(max >=  result[INFINITY].size())
     85             return max;
     86         else
     87         {//分别计算无穷大斜率的不同截距各有几个点
     88             map<int,int> m;//key为截距,即x点坐标,value为数量
     89             for(auto i = result[INFINITY].begin(); i != result[INFINITY].end(); i++)
     90             {//set没有下标操作
     91                 if(m.find(points[*i].x) != m.end()) 
     92                     m[points[*i].x] = 1;
     93                 else
     94                     m[points[*i].x]++;
     95             }
     96             for(auto const &i : m)
     97             {
     98                 if(i.second > max)
     99                     max = i.second;
    100             }
    101             return max;
    102         }
    103 */
    104     }
    105 
    106     void generatePoints(int n , vector<Point> &points)
    107     {
    108         srand(time(0));
    109         Point p;
    110         for(int i=0; i<n; i++)
    111         {
    112             p.x = rand();
    113             p.y = rand();
    114             points.push_back(p);
    115         }
    116     }
    117 };
    118 
    119 int main()
    120 {
    121     Solution sol;
    122     vector<Point> points;
    123 //    sol.generatePoints(6,points);
    124 /*
    125     points.push_back(Point());//点(0,0)
    126     points.push_back(Point(-1,-1));//点(-1,-1)
    127     points.push_back(Point(2,2));//点(2,2)
    128     //输出应为3,却输出4,有点重复计算了!
    129 */
    130 /*
    131     //测试用例:输出应为25
    132     Point test[]= {Point(40,-23),Point(9,138),Point(429,115),Point(50,-17),Point(-3,80), Point(-10,33), Point(5,-21), Point(-3,80), Point(-6,-65), Point(-18,26), Point(-6,-65), Point(5,72), Point(0,77), Point(-9,86), Point(10,-2), Point(-8,85), Point(21,130), Point(18,-6), Point(-18,26), Point(-1,-15), Point(10,-2), Point(8,69), Point(-4,63), Point(0,3), Point(-4,40), Point(-7,84), Point(-8,7), Point(30,154), Point(16,-5), Point(6,90), Point(18,-6), Point(5,77), Point(-4,77), Point(7,-13), Point(-1,-45), Point(16,-5), Point(-9,86), Point(-16,11), Point(-7,84), Point(1,76), Point(3,77), Point(10,67), Point(1,-37), Point(-10,-81), Point(4,-11), Point(-20,13), Point(-10,77), Point(6,-17), Point(-27,2), Point(-10,-81), Point(10,-1), Point(-9,1), Point(-8,43), Point(2,2), Point(2,-21), Point(3,82), Point(8,-1), Point(10,-1), Point(-9,1), Point(-12,42), Point(16,-5), Point(-5,-61), Point(20,-7), Point(9,-35), Point(10,6), Point(12,106), Point(5,-21), Point(-5,82), Point(6,71), Point(-15,34), Point(-10,87), Point(-14,-12), Point(12,106), Point(-5,82), Point(-46,-45), Point(-4,63), Point(16,-5), Point(4,1), Point(-3,-53), Point(0,-17), Point(9,98), Point(-18,26), Point(-9,86), Point(2,77), Point(-2,-49), Point(1,76), Point(-3,-38), Point(-8,7), Point(-17,-37), Point(5,72), Point(10,-37), Point(-4,-57), Point(-3,-53), Point(3,74), Point(-3,-11), Point(-8,7), Point(1,88), Point(-12,42), Point(1,-37), Point(2,77), Point(-6,77), Point(5,72), Point(-4,-57), Point(-18,-33), Point(-12,42), Point(-9,86), Point(2,77), Point(-8,77), Point(-3,77), Point(9,-42), Point(16,41), Point(-29,-37), Point(0,-41), Point(-21,18), Point(-27,-34), Point(0,77), Point(3,74), Point(-7,-69), Point(-21,18), Point(27,146), Point(-20,13), Point(21,130), Point(-6,-65), Point(14,-4), Point(0,3), Point(9,-5), Point(6,-29), Point(-2,73), Point(-1,-15), Point(1,76), Point(-4,77), Point(6,-29)};
    133     vector<Point> points(test,test+sizeof(test)/sizeof(Point));
    134     */
    135 /*
    136     points.push_back(Point(2,2));//
    137     points.push_back(Point(2,2));//
    138     points.push_back(Point(2,2));//
    139 */
    140 ///*
    141     //测试用例:重复点问题,accept=4
    142     points.push_back(Point(1,1));//0
    143     points.push_back(Point(1,1));//1
    144     points.push_back(Point(2,2));//2
    145     points.push_back(Point(2,2));//3
    146 //*/
    147 
    148 /*
    149     //测试用例:输出应为6
    150     points.push_back(Point(0,-12));//0
    151     points.push_back(Point(5,2));//1
    152     points.push_back(Point(2,5));//2
    153     points.push_back(Point(0,-5));//3
    154     points.push_back(Point(1,5));//4
    155     points.push_back(Point(2,-2));//5
    156     points.push_back(Point(5,-4));//6
    157     points.push_back(Point(3,4));//7
    158     points.push_back(Point(-2,4));//8
    159     points.push_back(Point(-1,4));//9
    160     points.push_back(Point(0,-5));//10
    161     points.push_back(Point(0,-8));//11
    162     points.push_back(Point(-2,-1));//12
    163     points.push_back(Point(0,-11));//13
    164     points.push_back(Point(0,-9));//14
    165 */
    166 
    167     for(auto const &i : points)
    168         cout << i.x << " "<<i.y<<endl;
    169     cout << sol.maxPoints(points)<<endl;
    170     return 0;
    171 }
    View Code

       

    参考:

    http://blog.csdn.net/linhuanmars/article/details/21060933

    http://blog.csdn.net/doc_sgl/article/details/17103427

     

  • 相关阅读:
    Reverse题的tips
    电子公文传输系统 团队作业(五):冲刺总结(第三天)
    webrtc sdp(会话传输协议)详解
    CentOS新系统开启网络
    FreeSWITCH Cookbook
    NetEngine AR V300R019 配置指南-IP业务(命令行)—— NAT
    将md(markdown)文件导出成pdf的最简单办法
    liblinear
    Accelerometer, Gyroscope, and Magnetometer Analysis with Matplotlib
    svmlight
  • 原文地址:https://www.cnblogs.com/dreamrun/p/4529073.html
Copyright © 2011-2022 走看看