力扣第149题-直线上最多的点数

199 阅读3分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第16天,点击查看活动详情

前言

力扣第149题 直线上最多的点数 如下所示:

给你一个数组 points ,其中 points[i] = [xi, yi] 表示 X-Y 平面上的一个点。求最多有多少个点在同一条直线上。

示例 1:

输入: points = [[1,1],[2,2],[3,3]]
输出: 3

示例 2:

输入: points = [[1,1],[3,2],[5,3],[4,1],[2,3],[1,4]]
输出: 4

一、思路

题目意思很简单,就是求直线上最多的点数。我们知道两个点可以确定一条直线。那么一个很朴素的想法就出来了,我们可以任选两个点,然后看经过这条直线的有多少个点。

大致的步骤如下所示:

  1. 选择不重复的两个点
  2. 利用斜率和截距看落在直线上有多少个点

我们知道 y = ax + b,且有 a = (y1 - y2)/(x1 - x2)。也就是说可以通过两个点先求出斜率 a就,再带入一个点求出截距 b。我就是通过如上的方法来判断落在直线上的点的,但是由于斜率是由浮点数存储的,恨不准确,所以没有办法通过下面的这个示例:

image.png

于是我换成了乘法,也就是不求具体的斜率了。只要满足 (y'-y1)(x'-x2) =(y'-y2)(x'-x1)(该式子由两点式转换而来的)即可。

如何优化?

你会发现实际运行中会有这种情况:已经选了和 a1a2 两个点,并计算出了经过 a1, a2 直线上的点个数。但是后续的 a2, a3 与经过 a1, a2 是同一条直线。也就是说同一条直线计算了多遍。

那如何避免这种情况呢?我们只需要存储直线斜率就可以了。只要斜率 k1 已经计算过了,就将其放入 哈希表 防止再次计算。

因为浮点数无法正确的表示斜率,所以哈希表中要存储 约分过后的分数,例如 6/3要约分后变为 2/1

二、实现

实现代码

实现代码中并未使用 哈希表 进行优化,此部分可自己实现

public int maxPoints(int[][] points) {
    int ret = 1;
    for (int i=0; i<points.length-1; i++){
        for (int j=i+1; j<points.length; j++){
            ret = Math.max(ret, pointsInLine(i, j, points));
        }
    }
    return ret;
}

public int pointsInLine(int p1, int p2, int[][] points){
    int ret = 2;
    int[] point1 = points[p1];
    int[] point2 = points[p2];
    for (int i=0; i<points.length; i++){
        if (i == p1 || i == p2)
            continue;
        // (y-y1)(x-x2) =(y-y2)(x-x1)
        if ((points[i][1] - point1[1]) * (points[i][0] - point2[0]) == (points[i][1] - point2[1]) * (points[i][0] - point1[0]))
            ret++;
    }
    return ret;
}

测试代码

public static void main(String[] args) {
    int[][] points = {{1,1},{3,2},{5,3},{4,1},{2,3},{1,4}};
    int[][] points1 = {{4,5},{4,-1},{4,0}};
    new Number149().maxPoints(points1);
}

结果

image.png

三、总结

感谢看到最后,非常荣幸能够帮助到你~♥

如果你觉得我写的还不错的话,不妨给我点个赞吧!如有疑问,也可评论区见~