给你一个数组 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 中的所有点 互不相同
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/max-points-on-a-line
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
1:每两个点之间求出斜率和相位,用一个长度为4的数组arr来记录。
(1)因为斜率有可能是分数,所以采用arr的前两位来记录此斜率:arr[0] 分母, arr[1]分子,所以需要先求出分母和分子的最大公约数来约分(采用辗转相除法)。
(2)数组的3, 4 位来记录这个这两个点和 X 轴相交的时候的坐标点,原理同上。
2:把这个数组转换为String,当作map的key,map的value 表示相同点的出现的次数。
3:因为每个点都有重复计算,并且计算的值是 1 + 2 + ... + n = value,为了求n,对value 乘以2 开方 +1。
4:当直线与X周平行的时候,需要单独判断,记录与Y周的交点作为key即可。
思路比较简单,就是实现比较耗时。。。
public int maxPoints(int[][] points) { int length = points.length; if (length < 3) { return length; } Map<String, Integer> map = new HashMap<>(length * length); int max = 1; String key; for (int i = 0; i < length - 1; i++) { for (int j = i + 1; j < length; j++) { int[] a = points[i]; int[] b = points[j]; int x = a[0] - b[0]; int y = a[1] - b[1]; if (y== 0) { key = String.valueOf(a[1]); } else { int min = min(x, y); x /= min; y /= min; int x1 = a[0] * y - a[1] * x; int y1 = y; min = min(x1, y1); x1 /= min; y1 /= min; int[] arr = new int[]{x, y, x1, y1}; key = Arrays.toString(arr); } Integer value = map.get(key); if (value == null) { map.put(key, 1); } else { map.put(key, value + 1); max = Math.max(value + 1, max); } } } return (int) Math.pow(max << 1, 0.5) + 1; } public static int min(int x, int y) { if (x == 0) { return y; } int a = x < 0 ? ~x + 1 : x; int b = y < 0 ? ~y + 1 : y; if (a < b) { int t = a; a = b; b = t; } while (b != 0) { if (a == b) { break; } else { int k = a % b; a = b; b = k; } } return x < 0 ? ~a + 1 : a; }