示例图
给定二维平面上的 N 点作为一对 (x, y) 坐标,我们需要找到位于同一条线上的最大点数。
例子:
输入:points[] = {-1, 1}, {0, 0}, {1, 1},
{2, 2}, {3, 3}, {3, 4}
输出:4
那么位于同一条线上的点的最大数量为 4,这些点分别是 {0, 0}, {1, 1}, {2, 2}, {3, 3}
我们可以通过以下方法解决上述问题 - 对于每个点 p,计算其与其他点的斜率,并使用地图记录有多少个点具有相同的斜率,通过这种方式我们可以找出有多少个点与 p 在同一条线上。对于每个点继续执行相同的操作并更新迄今为止找到的最大点数。
实施过程中需要注意以下几点:
1、如果两个点是 (x1, y1) 和 (x2, y2),则它们的斜率将是 (y2 – y1) / (x2 – x1),这可能是一个双精度值,并且可能导致精度问题。为了消除精度问题,我们将斜率视为对 ((y2 – y1), (x2 – x1)) 而不是比率,并在插入到映射之前通过它们的 gcd 减少对。在下面的代码点中,垂直或重复的点被单独处理。
2、如果我们使用c++ 中的 unordered_map或Java 中的 HashMap来存储斜率对,则解决方案的总时间复杂度将为 O(n^2),空间复杂度将为 O(n)。
示例代码:
# python3 program to find maximum number of 2D points that lie on the same line.
from collections import defaultdict
from math import gcd
from typing import DefaultDict, List, Tuple
IntPair = Tuple[int, int]
def normalized_slope(a: IntPair, b: IntPair) -> IntPair:
"""
Returns normalized (rise, run) tuple. We won't return the actual rise/run
result in order to avoid floating point math, which leads to faulty
comparisons.
See
https://en.wikipedia.org/wiki/Floating-point_arithmetic#Accuracy_problems
"""
run = b[0] - a[0]
# normalize undefined slopes to (1, 0)
if run == 0:
return (1, 0)
# normalize to left-to-right
if run < 0:
a, b = b, a
run = b[0] - a[0]
rise = b[1] - a[1]
# Normalize by greatest common divisor.
# math.gcd only works on positive numbers.
gcd_ = gcd(abs(rise), run)
return (
rise // gcd_,
run // gcd_,
)
def maximum_points_on_same_line(points: List[List[int]]) -> int:
# You need at least 3 points to potentially have non-collinear points.
# For [0, 2] points, all points are on the same line.
if len(points) < 3:
return len(points)
# Note that every line we find will have at least 2 points.
# There will be at least one line because len(points) >= 3.
# Therefore, it's safe to initialize to 0.
max_val = 0
for a_index in range(0, len(points) - 1):
# All lines in this iteration go through point a.
# Note that lines a-b and a-c cannot be parallel.
# Therefore, if lines a-b and a-c have the same slope, they're the same
# line.
a = tuple(points[a_index])
# Fresh lines already have a, so default=1
slope_counts: DefaultDict[IntPair, int] = defaultdict(lambda: 1)
for b_index in range(a_index + 1, len(points)):
b = tuple(points[b_index])
slope_counts[normalized_slope(a, b)] += 1
max_val = max(
max_val,
max(slope_counts.values()),
)
return max_val
print(maximum_points_on_same_line([
[-1, 1],
[0, 0],
[1, 1],
[2, 2],
[3, 3],
[3, 4],
]))
# This code is contributed by Jose Alvarado Torre
输出:
4
时间复杂度: O(n 2 logn),其中 n 表示字符串长度。
辅助空间:O(n)。