【LeetCode-哈希表/数学】直线上最多的点数

题目描述

给定一个二维平面,平面上有 n 个点,求最多有多少个点在同一条直线上。
示例:

输入: [[1,1],[2,2],[3,3]]
输出: 3
解释:
^
|
|        o
|     o
|  o  
+------------->
0  1  2  3  4

题目链接: https://leetcode-cn.com/problems/max-points-on-a-line/

思路

固定一个点,统计经过这个点的直线能穿过多少点,统计的方法就是求斜率。例如,当前固定的点为(x1, y1),(x2, y2)和(x1, y1)的斜率为 k1 =(y2-y1)/(x2-x1),如果另一个点(x3, y3)和(x1, y1)之间的斜率(y3-y1)/(x3-x1)和 k1 相等的话,那么 (x1, y1),(x2, y2),(x3, y3)就在同一条直线上。使用哈希表 unordered_map<string, int> lines 来存储直线包含的点数,lines[k] = n,表示经过当前点斜率为 k 的直线共包含 n 个点(加上当前点应该是 n+1 个点)。

我们存储的斜率是字符串型的,例如 "1/2",因为 "2/4" 和 "1/2" 是一样的,所以我们要提取分子和分母的最大公约数对分数进行约分。

代码如下:

class Solution {
public:
    int maxPoints(vector<vector<int>>& points) {
        if(points.size()<3) return points.size();

        int ans = 1;
        for(int i=0; i<points.size(); i++){
            unordered_map<string, int> lines;
            int duplicates = 0;  // 重复点的个数
            int maxCnt = 0;   // 要设为0,设为1的话[[1,1],[1,1],[1,1]]输入会出错
            for(int j=i+1; j<points.size(); j++){
                if(points[i][0]==points[j][0] && points[i][1]==points[j][1]){
                    duplicates++;
                    continue;
                }
                int diffX = points[i][0]-points[j][0];
                int diffY = points[i][1]-points[j][1];
                int divisor = gcd(diffX, diffY);  // 通过 divisor对分数进行约分
                string key = to_string(diffY/divisor)+"/"+to_string(diffX/divisor);  // 斜率的字符串形式
                lines[key]++;
                maxCnt = max(maxCnt, lines[key]);
            }
            ans = max(ans, maxCnt+duplicates+1);
        }
        return ans;
    }

    int gcd(int a, int b){
        if(b==0) return a;

        return gcd(b, a%b);
    }
};
  • 时间复杂度:O(n^2)
  • 空间复杂度:O(n)

参考

1、https://leetcode-cn.com/problems/max-points-on-a-line/solution/yong-xie-lu-by-powcai/
2、https://leetcode-cn.com/problems/max-points-on-a-line/solution/xie-lu-fa-by-likou-50/

原文地址:https://www.cnblogs.com/flix/p/13299178.html