Max Points on a Line - LeetCode

Max Points on a Line - LeetCode

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


这道题一看就能知道大概要怎么做,先选中vector第一个点A,然后遍历剩下的点Xi,求出剩下每个点Xi与A之间的坐标差,这个坐标差的几何含义A到Xi的向量(当然如果不用坐标差,用斜率也是可以的,确实有人这么做而且通过了,但是用斜率的话又会出现小数,除以0这种很麻烦的问题),然后用一个vector存这个向量,另一个vector的对应位置存点的个数。一次遍历过后就可以把A扔掉了(因为经过A的所有直线在这次遍历中都计算过了),然后选择vector中第二个点B,继续上述过程,直到最后一个点。

但是这道题目难的地方在于需要考虑很多特殊情况,比如垂直(如果判断时用了斜率,那么垂直的情况要另外讨论),重合(解决重合就用一个overlap记录重合点的个数),溢出(如果判断的时候用了x1 * y2 == x2 * y1,那么碰到x1 = 65526, y2 = 65536就会出现整型溢出,就算转成浮点数还是有数据会让你溢出,亲测)。

打了几个小时,换了三四种方法,把各种坑都踩了一遍,还是有溢出的bug,于是参考了一下答案。。
一份答案用了求最大公约数的方法,这样就判断的时候就不用x1 * y2 == x2 * y1了,可以用x1/gcd1 == x2/gcd2 && y1/gcd1 == y2/gcd2来判断。

然后让我觉得自己蠢爆的一个地方是答案用了map<pair<int, int>, int> lines ,而我用了两个vector。其实一开是我也想用map的,但是map<Point, int> 会出错,貌似是因为Point不能直接比较大小,所以没法排序,另外Point也不能直接用==判断相等,所以没法用unordered_map(其实还是因为我懒得写重载)。

下面是我的丑陋的代码

#include <iostream>
#include <cstdlib>
#include <cmath>
#include <map>
#include <set>
#include <vector>
using namespace std;

class Solution {
public:
    int maxPoints(vector<Point>& points) {
        vector<Point> p;
        vector<int> n;
        int mmax = 0, m = 0, tmax = 0, overlap = 0;
        if (points.size() != 0) {
            mmax = 1;
        }
        for (int i = 0; i < points.size(); i++) {
            tmax = 0;
            overlap = 0;
            for (int j = i+1; j < points.size(); j++) {
                int a = points[j].x - points[i].x;
                int b = points[j].y - points[i].y;
                if (a == 0 && b == 0) {
                    overlap += 1;
                } else {
                    int k;
                    int gcd = GCD(a,b);
                    if (gcd != 0) {
                        a /= gcd;
                        b /= gcd;
                    }

                    for(k = 0; k < p.size(); k++) {

                        if ((p[k]).x == a && (p[k]).y == b) {
                            n[k]++;
                            tmax = max(tmax, n[k]);
                            break;
                        }
                    }
                    if (k == p.size()) {
                        p.push_back(Point(a, b));
                        n.push_back(1);
                        if (tmax == 0) tmax++;
                    }
                }
            }
            mmax = max(mmax, tmax+overlap+1);
            p.clear();
            n.clear();
        }
        return mmax;
    }

    int GCD(int a, int b) {
        if (b == 0) return a;
        else return GCD(b, a%b);
    }
};

下面是别人的优美的代码

class Solution {
public:
    int maxPoints(vector<Point> &points) {

        if(points.size()<2) return points.size();

        int result=0;

        for(int i=0; i<points.size(); i++) {

            map<pair<int, int>, int> lines;
            int localmax=0, overlap=0, vertical=0;

            for(int j=i+1; j<points.size(); j++) {

                if(points[j].x==points[i].x && points[j].y==points[i].y) {

                    overlap++;
                    continue;
                }
                else if(points[j].x==points[i].x) vertical++;
                else {

                    int a=points[j].x-points[i].x, b=points[j].y-points[i].y;
                    int gcd=GCD(a, b);

                    a/=gcd;
                    b/=gcd;

                    lines[make_pair(a, b)]++;
                    localmax=max(lines[make_pair(a, b)], localmax);
                }

                localmax=max(vertical, localmax);
            }

            result=max(result, localmax+overlap+1);
        }

        return result;
    }

private:
    int GCD(int a, int b) {

        if(b==0) return a;
        else return GCD(b, a%b);
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值