题目
给你一个数组 points ,其中 points[i] = [xi, yi] 表示 X-Y 平面上的一个点。求最多有多少个点在同一条直线上。
- 示例 1:
输入:points = [[1,1],[2,2],[3,3]]
输出:3
- 示例 2:
输入:points = [[1,1],[3,2],[5,3],[4,1],[2,3],[1,4]]
输出:4
提示:
- 1 <= points.length <= 300
- points[i].length == 2
- -104 <= xi, yi <= 104
- points 中的所有点 互不相同
解题思路
- 遍历每一个点标i,以点标i为原点向后遍历后面的所有点标,记作j,计算i与j之间的斜率和截距(因为统一以i为起点,所以不需要计算截距,只需要用斜率就能表示一条直线)
- 使用map记录斜率,因为都经过点标i,所以相同斜率即为同一条直线上的点,考虑到斜率可能是小数的精度问题,因此将斜率化成最简分数的形式(使用辗转相除法求最大公约数),再使用字符串进行表示。最后,斜率相同的直线个数+1(因为一条直线是由两个点表示的,因此n条直线里面含有n+1个点),就是处于同一直线下的点标数量。
辗转相除法
做法:用较大数除以较小数,再用出现的余数(第一余数)去除除数,再用出现的余数(第二余数)去除第一余数,如此反复,直到最后余数是0为止。
代码
class Solution {int gcd(int a, int b) {return b == 0 ? a : gcd(b, a % b);}public int maxPoints(int[][] points) {int n=points.length,res=1;for (int i = 0; i < n; i++) {HashMap<String, Integer> map = new HashMap<>();int x1=points[i][0],y1=points[i][1];int max=0;for (int j = i+1; j < n; j++) {int x2=points[j][0],y2=points[j][1];int a=x1-x2,b=y1-y2;int gcd = gcd(a, b);String key = (a / gcd) + " " + (b / gcd);map.put(key,map.getOrDefault(key,0)+1);max=Math.max(max,map.get(key));}res=Math.max(res,max+1);}return res;}
}