leetcode 149. Max Points on a Line

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

给定一个平面及其上面若干个点,求最大的位于同一直线上的点的个数

/**
 * Definition for a point.
 * class Point {
 *     int x;
 *     int y;
 *     Point() { x = 0; y = 0; }
 *     Point(int a, int b) { x = a; y = b; }
 * }
 */
public int maxPoints(Point[] points) {}

求在同一直线上的点,很容易想到就是求斜率,那么就是算(y1-y2)/(x1-x2),把任意两点的斜率算出来,找到出现次数最大的斜率即可。
注意点:

  1. 不能直接算出所有两点的斜率然后加总,因为会出现重复计算,比如4个在同一直线上的,那么组合方式就有6种,实际只有4个点,正确的方式应该是对任意一点,求它跟其他所有点形成的斜率出现的最大次数。
  2. 不能直接用浮点数存储斜率,double也不行,因为斜率有可能无穷大,那么这时需要换另一种方式,以分数形式表达斜率。而分数形式表达斜率,需要约分成最简形式,即求出分子分母的最大公约数,这里可以用辗转相除法求得
  3. 出现的点有可能是重复点,那么两个重复点可以看做能够形成任意斜率,因此针对每个点计算加总时,要把这种点的重复点也考虑进去。此外还要考虑斜率无穷大时的情况,因为这时分母=0,要特别注意。
public int maxPoints(Point[] points) {
        if(points.length == 0){
            return 0;
        }
        int max = 0;
        for(int i=0;i<points.length;i++){
            Map<Point,Integer>map = new HashMap<Point,Integer>();
            int repeatCount = 0;//重复点
            boolean maxChange = false;
            int count = 0;
            for(int j = i+1;j<points.length;j++){
                if(points[i].x == points[j].x && points[i].y == points[j].y){//重复点
                    repeatCount++;
                }
                else{
                    boolean contains = false;
                    //这里的p是用来记录i,j两点的分数形式表示的斜率
                    Point p = null;
                    if(points[i].x == points[j].x){
                        p = new Point(0,1);
                    }
                    else if(points[i].y == points[j].y){
                        p = new Point(1,0);
                    }
                    else{
                        int greaestDiv = greatestDivisor(points[i].y - points[j].y,points[i].x - points[j].x);
                        p  = new Point(
                                (points[i].y - points[j].y)/greaestDiv,(points[i].x - points[j].x)/greaestDiv);
                    }

                    for(Map.Entry<Point, Integer> entry : map.entrySet()){
                        if(p.x == entry.getKey().x && p.y == entry.getKey().y){
                            map.put(entry.getKey(), entry.getValue()+1);
                            contains = true;
                            count = entry.getValue();
                            break;
                        }
                    }
                    if(!contains){
                        map.put(p,1);
                        count = 1;
                    }
                    if(count > max){
                        max = count;
                        maxChange = true;
                    }
                }
            }
            if(repeatCount > max){//最多出现的就是重复点
                max = repeatCount;
            }
            if(maxChange){//内层循环更新了最大值
                max += repeatCount;
            }
        }
        return max+1;

    }

    public int greatestDivisor(int x,int y){
        if(x == 0){
            return y;   
        }
        else if(Math.abs(x) > Math.abs(y)){
            return greatestDivisor(x%y,y);
        }
        else{
            return greatestDivisor(y%x,x);
        }
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值