1. 程式人生 > 其它 >leetcode 149. 直線上最多的點數

leetcode 149. 直線上最多的點數

給你一個數組 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; }