python 计算同一行上的最大点数(Count maximum points on same line)

示例图 

        给定二维平面上的 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_mapJava 中的 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)。 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值