[LC] 149. 直线上最多的点数

195 阅读1分钟

149. 直线上最多的点数

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

本题收获

  1. 此类题目可以使用分数来表示斜率
  2. 对分数约分
  3. 分子分母使用一个int能表示的整数,并利用哈系表保存其(分子分母组合出的唯一值)个数,即可得到相同斜率的个数。
class Solution
{
public:
    int gcd(int a, int b)
    {
        return b ? gcd(b, a % b) : a;
    }
    
    int maxPoints(vector<vector<int>> &points)
    {
        int n = points.size();
        if (n <= 2)
            return n;
        int res = 0;
        for (int i = 0; i < n; i++)
        {
            // 因为第i个节点后最长的直线也只能有n-i个点
            // 如果最大的结点数已经达到n的一半了,则没有必要再往后找了
            if (n - i <= res || res > n / 2) 
                break;
            unordered_map<int, int> mp; // 使用哈希记录每个斜率数对的个数
            for (int j = i + 1; j < n; j++)
            {
                int x = points[j][0] - points[i][0];
                int y = points[j][1] - points[i][1];
                if (x == 0)
                    y = 1;
                else if (y == 0)
                    x = 1;
                else
                {
                    if (y < 0)
                    {
                        x = -x;
                        y = -y;
                    }
                    int gcdXY = gcd(abs(x), abs(y));
                    x = x / gcdXY, y = y / gcdXY;
                }
                // 此处y的范围是[0, 20000],之所以要加上x*20001是因为其值肯定大于y,所以对于不同的x,y总是能得到不同的值。
                // 例如y = [1, 2] x = [3, 4] 则x,y取不同的值只会得到唯一值,而y = [1, 2, 3] x = [1, 2, 3] 则x,y取不同的值,可能会得到相同的值
                mp[y + x * 20001]++;
            }
            int maxn = 0;
            for (auto &[_, num] : mp)
            {
                maxn = max(maxn, num + 1);
            }
            res = max(res, maxn);
        }
        return res;
    }
};