149. 直线上最多的点数 Max Points on a Line

该博客讨论了一种算法问题,即在给定的二维平面上,如何找出最多有多少个点位于同一直线上。作者提出使用哈希表存储斜率及其出现次数,并通过辗转相除法求斜率的最简分数形式。算法的时间复杂度为O(n^2),空间复杂度为O(n)。解决方案包括处理特殊情况、遍历所有点作为起点并计算斜率、更新最大点数等步骤。
摘要由CSDN通过智能技术生成
  1. 直线上最多的点数
    给定一个二维平面,平面上有 n 个点,求最多有多少个点在同一条直线上。

示例 1:

在这里插入图片描述

示例 2:

在这里插入图片描述
我的解题:
哈希法
思路:判断一个点是否在直线上,只需要一个起始点和斜率。用一个for循环遍历所有点作为起始点,然后遍历剩下的元素的斜率。因为斜率可能是小数,所以用求得最简约分的分数表示。将斜率存储在hashmap中,value存储出现次数。求得次数最高的点数+1即可
做法:
1、判断特殊情况,为空或者数组数量小于3
2、遍历数组,依次作为起始点。
3、遍历剩下的元素,求得最大公约数,求得斜率分数最简约分。这里要判断当dy=0时斜率为0,dx=0是斜率用oo表示
4、以斜率为key在map中获取值。如果不存在,则存入该斜率,值为1。否则值+1、并且判断更新最大数量
时间复杂度:O(n^2),空间复杂度O(n)

辗转相除求最大公约数法
这里需要用辗转相除法。如果自己写,用for的方式求最大公约数会超时。

private static int getGcd(int dy, int dx) {
    while (dy != 0) {
        int temp = dx % dy;
        dx = dy;
        dy = temp;
    }
    return dx;
}

最终代码:

class Solution {
    public static int maxPoints(int[][] points) {
        //判断特殊情况
        if (points == null || points.length == 0) return 0;
        //当数组长度为1时返回1
        if (points.length == 1) return 1;

        //定义最大数量
        int maxNum = 1;
        //遍历数组作为起始点
        for (int i = 0; i < points.length; i++) {
            //存储斜率,找到最大数量
            Map<String, Integer> map = new HashMap<>();
            //遍历剩下的元素
            for (int j = 0; j < points.length; j++) {
                if (i == j) continue;   //本元素跳过
                int dx = points[j][0] - points[i][0];
                int dy = points[j][1] - points[i][1];

                String k;
                if (dy == 0) k = "0";   //当dy=0是斜率为“0”
                else if (dx == 0) k = "oo"; //当dx=0是斜率为“oo”,否则会报/0异常
                else {
                    //求得最大公约数
                    int gcd = getGcd(dy, dx);
                    //将斜率最简约分作为字符串形式
                    k = dy/gcd + "/" + dx/gcd;
                }

                //将斜率放到map中或者value+1
                Integer getVal = map.get(k);
                if (getVal == null) map.put(k, 1);
                else {
                    map.put(k, ++getVal);
                    //更新最大值
                    if (maxNum < getVal) maxNum = getVal;
                }
            }
        }
        //这里要+1,因为要加上起始元素
        return maxNum+1;
    }

    //辗转相除求最大公约数法
    //这里需要用辗转相除法。如果自己写,用for的方式求最大公约数会超时。
    //求dy/dx的最简分数的字符串
    private static int getGcd(int dy, int dx) {
        while (dy != 0) {
            int temp = dx % dy;
            dx = dy;
            dy = temp;
        }
        return dx;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值