当前位置: 面试刷题>> 直线上最多的点数(经典算法150题)


### 题目描述 题目:**直线上最多的点数** 给定一个二维平面上的点集,每个点由一对整数坐标 `(x, y)` 表示。现在,我们需要找出这些点中,能构成最多点数的直线(即,在同一直线上的点数最多)。返回这条直线上点的数量。 **注意**: 1. 两点确定一条直线,但如果三点或更多点共线,则这些点都视为在同一直线上。 2. 坐标值在 `int` 范围内。 3. 输入的点集中不包含重复的点。 ### 示例 输入:`[[1,1],[2,2],[3,3]]` 输出:`3` 解释:这三个点在同一直线上。 输入:`[[1,1],[2,2],[3,4],[1,0],[4,5],[2,1]]` 输出:`2` 解释:最长直线是 `(1,1)` 和 `(2,2)`,或者 `(2,1)` 和 `(4,5)`,它们都包含2个点。 ### 解题思路 为了解决这个问题,我们可以使用哈希表来存储斜率(或直线的另一种表示方式)和对应的点数。对于每一点,我们计算它与其他所有点形成的斜率(为了避免分母为0的情况,可以使用 `y2-y1` 除以 `x2-x1` 的方式,如果 `x` 坐标相同,则直接比较 `y` 坐标)。然后,我们使用这些斜率(或特定表示方式)来更新哈希表中对应直线的点数。 ### PHP 代码示例 ```php function maxPoints($points) { $n = count($points); if ($n <= 2) { return $n; } $maxCount = 0; for ($i = 0; $i < $n; $i++) { $slopes = []; $duplicatePoints = 0; $maxCurrent = 0; for ($j = $i + 1; $j < $n; $j++) { if ($points[$i][0] == $points[$j][0] && $points[$i][1] == $points[$j][1]) { $duplicatePoints++; continue; } $x1 = $points[$i][0]; $y1 = $points[$i][1]; $x2 = $points[$j][0]; $y2 = $points[$j][1]; if ($x1 == $x2) { $slope = 'INF'; // 垂直线 } else { $slope = ($y2 - $y1) . '/' . ($x2 - $x1); } if (!isset($slopes[$slope])) { $slopes[$slope] = 1; } else { $slopes[$slope]++; } $maxCurrent = max($maxCurrent, $slopes[$slope]); } $maxCount = max($maxCount, $maxCurrent + $duplicatePoints + 1); } return $maxCount; } ``` ### Python 代码示例 ```python def maxPoints(points): n = len(points) if n <= 2: return n max_count = 0 for i in range(n): slopes = {} duplicate_points = 0 max_current = 0 for j in range(i + 1, n): if points[i] == points[j]: duplicate_points += 1 continue x1, y1 = points[i] x2, y2 = points[j] if x1 == x2: slope = 'INF' else: slope = (y2 - y1) / (x2 - x1) slopes[slope] = slopes.get(slope, 0) + 1 max_current = max(max_current, slopes[slope]) max_count = max(max_count, max_current + duplicate_points + 1) return max_count ``` ### JavaScript 代码示例 ```javascript function maxPoints(points) { const n = points.length; if (n <= 2) return n; let maxCount = 0; for (let i = 0; i < n; i++) { const slopes = {}; let duplicatePoints = 0; let maxCurrent = 0; for (let j = i + 1; j < n; j++) { if (points[i][0] === points[j][0] && points[i][1] === points[j][1]) { duplicatePoints++; continue; } const [x1, y1] = points[i]; const [x2, y2] = points[j]; let slope; if (x1 === x2) { slope = 'INF'; } else { slope = `${(y2 - y1)}/${(x2 - x1)}`; } if (!slopes[slope]) { slopes[slope] = 1; } else { slopes[slope]++; } maxCurrent = Math.max(maxCurrent, slopes[slope]); } maxCount = Math.max(maxCount, maxCurrent + duplicatePoints + 1); } return maxCount; } ``` 以上代码示例中,我们遍历了所有点对,并计算了它们之间的斜率(或特殊表示方式),以此来判断它们是否在同一直线上。最终,我们返回了构成最多点数的直线上的点数。