149. 直线上最多的点数(困难)



 
枚举直线 + 哈希表统计
思路
-  遍历每两个点之间的连线,然后计算这条连线上有多少个点。 
 具体步骤如下:- 初始化最大点数为 0。
- 遍历每个点,用它和其他点计算斜率。
- 如果两个点的x坐标相同,斜率设为INT_MAX;否则,计算斜率,即两个点的y 差值除以 x 差值。
- 使用一个哈希表mp来记录每个斜率对应的点的个数,初始值为2(两个点)。
- 遍历其他点,如果它们和当前点的斜率相同,则将对应斜率的点数加1。
- 更新最大点数为mp中的最大值。
- 返回最大点数。
 
-  为了避免重复计算,使用一个 flag 数组来标记已经处理过的点。在内层循环中,如果一个点已经被标记过,则直接跳过。 
-  这个思路的时间复杂度为O(n2),因为需要两重循环来遍历所有的点对。 
-  缺点:在每次遍历点集之前都创建了一个新的 flag 数组和 mp 哈希表,这样会导致重复的计算。 
易错点
- 错误处理斜率不存在(即两个点横坐标相同)的情况,将 k 标记为 0;
- 斜率可能为浮点数,一开始也标记为 int ;
- 一开始将 flag 数组 和 mp 哈希表放在大循环外边,导致有些点没有计算到。
代码
class Solution {
public:
    int maxPoints(vector<vector<int>>& points) {
        int n = points.size();
        if(n < 3)   return n;
        int maxPoint = 0;
        
        for(int i=0; i<n-1; ++i){
            vector<int> flag(n, 0);
            unordered_map<double, int> mp;
            if(flag[i]) continue;
            flag[i] = 1;
            for(int j=i+1; j<n; ++j){
                if(flag[j]) continue;
                flag[j] = 1;
                double k;
                // 斜率=0
                if(points[j][0] == points[i][0]) k = INT_MAX;
                else k = (double)(points[j][1] - points[i][1]) / (double)(points[j][0] - points[i][0]);
                mp[k] += 2;
                for(int p=j+1; p<n; ++p){
                    if(flag[p]) continue;
                    // 在同一条直线上
                    if(points[p][0] == points[j][0] && k == INT_MAX){
                        flag[p] = 1;
                        mp[k] ++;
                    }
                    if(((double)(points[p][1] - points[j][1]) / (double)(points[p][0] - points[j][0])) == k){
                        flag[p] = 1;
                        mp[k] ++;
                    }
                }
            }
            for(auto key : mp){
                maxPoint = max(maxPoint, key.second);
            }
        }
        return maxPoint;
    }
};



















