哈希表:直线上最多的点——03(hard)

题目:

给定一些二维坐标中的点,求同一条线上最多由多少点。

思路:

对于每个点,我们对其它点建立哈希表,统计同一斜率的点一共有多少个。这里利用的原理
是,一条线可以由一个点和斜率而唯一确定。另外也要考虑斜率不存在和重复坐标的情况。
本题也利用了一个小技巧:在遍历每个点时,对于数组中位置 i 的点,我们只需要考虑 i 之
后的点即可,因为 i 之前的点已经考虑过 i 了。

四个小优化:

1.在点的总数量小于等于 2 的情况下,我们总可以用一条直线将所有点串联,此时我们直接返回点的总数量即可;
2.当我们枚举到点 i 时,我们只需要考虑编号大于 i 的点到点 i 的斜率,因为如果直线同时经过编号小于点 i 的点 j,那么当我们枚举到 j 时就已经考虑过该直线了;
3.当我们找到一条直线经过了图中超过半数的点时,我们即可以确定该直线即为经过最多点的直线;
4.当我们枚举到点 i(假设编号从 0 开始)时,我们至多只能找到 n−i 个点共线。假设此前找到的共线的点的数量的最大值为 k,如果有 k≥n−i,那么此时我们即可停止枚举,因为不可能再找到更大的答案了。

class Solution {
    public int maxPoints(int[][] points) {
       int n = points.length;
       if (n <= 2){
           return n;
       }
       int ret = 0;
       for (int i= 0; i < n; i++){
           if (ret >= n - i || ret > n/2){
               break;
           }
           Map<Integer, Integer>map = new HashMap<Integer,Integer>();
           for (int j = i+1; j < n; j++){
               int x = points[i][0] - points[j][0];
               int y = points[i][1] - points[j][1];
               if (x == 0){
                   y = 1;
               } else if (y ==0){
                   x = 1;
               }else {
                   if (y < 0){
                       x =-x;
                       y =-y;
                   }
                   int gcdXY = gcd(Math.abs(x), Math.abs(y));
                   x /=gcdXY;
                   y /=gcdXY;
               }
               int key = y + x *20001;
               map.put(key,map.getOrDefault(key,0) + 1);
           }
           int maxn = 0;
           for (Map.Entry<Integer,Integer> entry:map.entrySet()){
               int num = entry.getValue();
               maxn = Math.max(maxn, num+1);
           }
           ret = Math.max(ret,maxn);
       }
       return ret;
    }
    public int gcd(int a, int b){
        return b !=0 ? gcd(b,a%b):a;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一只程序小洋

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值