题目描述
给你一个数组 points
,其中 points[i] = [xi, yi]
表示 X-Y 平面上的一个点。求最多有多少个点在同一条直线上。
解题思路
我们可以考虑枚举所有的点,计算直线经过该点时,该直线所能经过的最多的点数。
假设我们当前枚举到点 i,如果直线同时经过另外两个不同的点 j 和 k,那么可以发现点i和点j所连直线的斜率恰等于点 i和点 k 所连直线的斜率。反之亦然。
于是我们可以统计其他所有点与点 i 所连直线的斜率,出现次数最多的斜率即为经过点数最多的直线的斜率。
优化
三个小优化:
- 在点的总数量小于等于 2 的情况下,我们总可以用一条直线将所有点串联,此时我们直接返回点的总数量即可;
- 当我们枚举到点 i 时,我们只需要考虑编号大于 i 的点到点 i 的斜率,因为如果直线同时经过编号小于点 i 的点 j,那么当我们枚举到 j 时就已经考虑过该直线了;
- 当我们枚举到点 i(假设编号从 0 开始)时,我们至多只能找到 n - i 个点共线。假设此前找到的共线的点的数量的最大值为 k,如果有 k ≥ n - i,那么此时我们即可停止枚举,因为不可能再找到更大的答案了。
AC代码(JS)
/**
* @param {number[][]} points
* @return {number}
*/
var maxPoints = function(points) {
const n = points.length;
if (n <= 2) {
return n;
}
let maxNum = 0;
for(let i = 0; i < n - 1; i++) {
if (maxNum >= n - i) {
break;
}
const myMap = new Map();
for (let j = i + 1; j < n; j++) {
let k = (points[j][1] - points[i][1]) / (points[j][0] - points[i][0]);
if (k == -Infinity) {
k = Infinity;
}
if (myMap.has(k)) {
myMap.set(k, myMap.get(k) + 1);
}
else {
myMap.set(k, 2);
}
}
for (var value of myMap.values()) {
maxNum = Math.max(maxNum, value);
}
}
return maxNum;
};