跳转至

149.直线上最多的点 (Hard)*

题目描述*

标签*

哈希表;数学;

思路 & 代码*

暴力方法就是对每条直线判断有几个点在上面,优化可以把方程存起来,不用重复统计。主要的问题感觉就是斜率的比较,因为肯定会有小数,想用分数表示就得实现约分化简,如果用乘法代替除法判等还得考虑溢出。

或者可以从点出发,求过这个点的直线上点最多的。感觉严谨的做法还是得用分数比较斜率,后面还写了一个追求速度的版本,先按照差值排序,这样判断重复点比较方便。

class Solution {
private:
    int gcd(int a, int b) {
        // return b == 0 ? a : gcd(b, a % b);
        if(a < b) {
            a ^= b;
            b ^= a;
            a ^= b;
        }
        while(b) {
            int tmp = a % b;
            a = b;
            b = tmp;
        }
        return a;
    }
    bool test(int x1, int y1, int x2, int y2, int x, int y) {
        if(x == x2 && y == y2 || x == x1 && y == y1) {
            return true;
        }
        int g1 = gcd(y2 - y1, x2 - x1);
        int g2 = gcd(y - y2, x - x2);
        // 负数的话还可能是正负号反过来
        return (y2 - y1) / g1 == (y - y2) / g2 && (x2 - x1) / g1 == (x - x2) / g2 ||
            (y2 - y1) / g1 == -1 * (y - y2) / g2 && (x2 - x1) / g1 == -1 *(x - x2) / g2;        
    }
public:
    int maxPoints(vector<vector<int>>& points) {
        int len = points.size();
        if(len < 3) {
            return len;
        }
        int i = 0;
        while(i < len - 1 && points[i][0] == points[i + 1][0] && points[i][1] == points[i + 1][1]) {
            i++;
        }
        if(i == len - 1) {
            return len;
        }
        int res = 0;
        for(int i = 0; i < len; i++) {
            for(int j = i + 1; j < len; j++) {
                if(points[i][0] == points[j][0] && points[i][1] == points[j][1]) {
                    continue;
                }
                int cur = 0;
                for(int k = 0; k < len; k++) {
                    if(k != i && k != j) {
                        if(test(points[i][0], points[i][1], points[j][0], points[j][1], points[k][0], points[k][1])) {
                            cur++;
                        }
                    }
                }
                if(cur > res) {
                    res = cur;
                }
            }
        }
        return res + 2;
    }
};
class Solution {
public:
    int maxPoints(vector<vector<int>>& points) {
        int len = points.size();
        if(len < 3) {
            return len;
        }
        int res = 0;
        for(int i = 0; i < len; i++) {
            int same = 0;
            int curMax = 0;
            unordered_map<string, int> lines;
            for(int j = i + 1; j < len; j++) {
                int x = points[j][0] - points[i][0];
                int y = points[j][1] - points[i][1];
                if(x == 0 && y == 0) {
                    same++;
                    continue;
                }
                int g = gcd(x, y);
                x /= g, y /= g;
                string prefix = "+";
                if(x < 0 && y > 0 || x > 0 && y < 0) {
                    prefix = "-";
                }
                x = abs(x);
                y = abs(y);                    
                string key = prefix + to_string(x) + "/" + to_string(y);
                lines[key]++;
                curMax = max(lines[key], curMax);
            }
            res = max(curMax + same + 1, res);
        }
        return res;
    }
};
class Solution {
public:
    int maxPoints(vector<vector<int>>& points) {
        int len = points.size();
        if(len < 3) {
            return len;
        }
        // 按照坐标差值排序
        sort(points.begin(), points.end(), [&](const vector<int>& a, const vector<int>& b) -> int {
            return abs(a[0] - a[1]) < abs(b[0] - b[1]);
        });
        int res = 0;
        for(int i = 1; i < len; i++) {
            int x = points[i][0];
            int y = points[i][1];
            int dx = x - points[i - 1][0];
            int dy = y - points[i - 1][1];
            int cnt = 0;
            if(dx == 0 && dy == 0) {
                for(int j = 0; j < len; j++) {
                    cnt += (points[j][0] == x && points[j][1] == y);
                }
            }else {
                for(int j = 0; j < len; j++) {
                    cnt += ((points[j][1] - y) * static_cast<long>(dx) == static_cast<long>(dy) * (points[j][0] - x));
                }
            }
            res = max(res, cnt);
        }
        return res;
    }
};

最后更新: July 23, 2022