【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/