問題:
Given n points on a 2D plane, find the maximum number of points that lie on the same straight line.
給定一個二維平面,平面上有 n 個點,求最多有多少個點在同一條直線上。
分析:
根據兩點確定一條直線原理,我們可以選取兩個點確定一條直線,再看看其他的點有多少位於這條直線上,這題主要思路就這麼簡單,之所以是個困難題,因爲有很多特殊情況要考慮
第一,斜率的計算,如果用除法計算斜率,會有斜率爲無窮大的問題,另外除法的結果是浮點數,可能會有不精確的問題,所以我們使用乘法來進行斜率的比較,當然乘法也要注意,int的乘法結果可能會超出上限,要用long來保存乘法結果
第二,重複點的問題,如果一開始選取用來確定一條直線的兩個點是重複點就會造成問題,應該跳過這種情況
代碼:
/**
* 直線上最多的點數
* Max Points on a Line
*
* @author DongWei
* @date 2019/5/22
*/
class Solution {
public int maxPoints(int[][] points) {
// 如果總座標點少於 3 個,直接返回答案
int n = points.length;
if (points.length <= 2) return n;
// 搜索直線上最多的點數
int max = 0;
for (int i = 0; i < n; i ++) {
// same 表示有多少個和 i 一樣的點
int same = 1;
for (int j = i + 1; j < n; j ++) {
// cnt 表示除了 i 座標點外,有多少個點在 i、j 座標點構成的直線上
int cnt = 0;
if (points[i][0] == points[j][0] && points[i][1] == points[j][1]) {
// i、j 是重複點,計數
same ++;
} else {
// i、j 不是重複點,檢查其他點是否在這條直線上,j 座標點也在這條直線上,所以 cnt ++
cnt ++;
long xDiff = (long)(points[i][0] - points[j][0]);
long yDiff = (long)(points[i][1] - points[j][1]);
for (int k = j + 1; k < n; k ++) {
if (xDiff * (points[i][1] - points[k][1]) == yDiff * (points[i][0] - points[k][0])) {
cnt ++;
}
}
}
// 最大值比較
max = Math.max(max, cnt + same);
}
}
return max;
}
}
這個代碼跑起來在20ms以內,最快能到10ms,每次結果都不一樣