- 直线上最多的点数
给定一个二维平面,平面上有 n 个点,求最多有多少个点在同一条直线上。
示例 1:
示例 2:
我的解题:
哈希法
思路:判断一个点是否在直线上,只需要一个起始点和斜率。用一个for循环遍历所有点作为起始点,然后遍历剩下的元素的斜率。因为斜率可能是小数,所以用求得最简约分的分数表示。将斜率存储在hashmap中,value存储出现次数。求得次数最高的点数+1即可
做法:
1、判断特殊情况,为空或者数组数量小于3
2、遍历数组,依次作为起始点。
3、遍历剩下的元素,求得最大公约数,求得斜率分数最简约分。这里要判断当dy=0时斜率为0,dx=0是斜率用oo表示
4、以斜率为key在map中获取值。如果不存在,则存入该斜率,值为1。否则值+1、并且判断更新最大数量
时间复杂度:O(n^2),空间复杂度O(n)
辗转相除求最大公约数法
这里需要用辗转相除法。如果自己写,用for的方式求最大公约数会超时。
private static int getGcd(int dy, int dx) {
while (dy != 0) {
int temp = dx % dy;
dx = dy;
dy = temp;
}
return dx;
}
最终代码:
class Solution {
public static int maxPoints(int[][] points) {
//判断特殊情况
if (points == null || points.length == 0) return 0;
//当数组长度为1时返回1
if (points.length == 1) return 1;
//定义最大数量
int maxNum = 1;
//遍历数组作为起始点
for (int i = 0; i < points.length; i++) {
//存储斜率,找到最大数量
Map<String, Integer> map = new HashMap<>();
//遍历剩下的元素
for (int j = 0; j < points.length; j++) {
if (i == j) continue; //本元素跳过
int dx = points[j][0] - points[i][0];
int dy = points[j][1] - points[i][1];
String k;
if (dy == 0) k = "0"; //当dy=0是斜率为“0”
else if (dx == 0) k = "oo"; //当dx=0是斜率为“oo”,否则会报/0异常
else {
//求得最大公约数
int gcd = getGcd(dy, dx);
//将斜率最简约分作为字符串形式
k = dy/gcd + "/" + dx/gcd;
}
//将斜率放到map中或者value+1
Integer getVal = map.get(k);
if (getVal == null) map.put(k, 1);
else {
map.put(k, ++getVal);
//更新最大值
if (maxNum < getVal) maxNum = getVal;
}
}
}
//这里要+1,因为要加上起始元素
return maxNum+1;
}
//辗转相除求最大公约数法
//这里需要用辗转相除法。如果自己写,用for的方式求最大公约数会超时。
//求dy/dx的最简分数的字符串
private static int getGcd(int dy, int dx) {
while (dy != 0) {
int temp = dx % dy;
dx = dy;
dy = temp;
}
return dx;
}
}