有效的回旋镖

标签: 几何 数组 数学

难度: Easy

给定一个数组 points ,其中 points[i] = [xi, yi] 表示 X-Y 平面上的一个点,如果这些点构成一个 回旋镖 则返回 true 。

回旋镖 定义为一组三个点,这些点 各不相同 且 不在一条直线上 。

示例 1:

输入:points = [[1,1],[2,3],[3,2]]
输出:true

示例 2:

输入:points = [[1,1],[2,2],[3,3]]
输出:false

提示:

  • points.length == 3
  • points[i].length == 2
  • 0 <= xi, yi <= 100

Submission

运行时间: 19 ms

内存: 16.1 MB

from typing import List

class Solution:
    def isBoomerang(self, points: List[List[int]]) -> bool:
        # 检查两个斜率是否相等来判断三个点是否共线
        def isCollinear(p1, p2, p3):
            # 斜率公式:(y2 - y1) / (x2 - x1)
            slope1 = (p2[1] - p1[1]) / (p2[0] - p1[0]) if p2[0] != p1[0] else float('inf')
            slope2 = (p3[1] - p1[1]) / (p3[0] - p1[0]) if p3[0] != p1[0] else float('inf')
            return slope1 == slope2

        p1, p2, p3 = points
        # 如果三个点中有任意两个点重合,它们不构成回旋镖
        if p1 == p2 or p1 == p3 or p2 == p3:
            return False
        # 如果三个点共线,它们也不构成回旋镖
        return not isCollinear(p1, p2, p3)

Explain

这个题解的思路是首先检查三个点是否有任意两个点重合,如果有,则它们不构成回旋镖。接着,使用斜率公式判断这三个点是否共线,如果共线,它们也不构成回旋镖。只有当三个点各不相同且不共线时,它们才构成一个回旋镖。

时间复杂度: O(1)

空间复杂度: O(1)

from typing import List

class Solution:
    def isBoomerang(self, points: List[List[int]]) -> bool:
        # 检查两个斜率是否相等来判断三个点是否共线
        def isCollinear(p1, p2, p3):
            # 斜率公式:(y2 - y1) / (x2 - x1)
            slope1 = (p2[1] - p1[1]) / (p2[0] - p1[0]) if p2[0] != p1[0] else float('inf')
            slope2 = (p3[1] - p1[1]) / (p3[0] - p1[0]) if p3[0] != p1[0] else float('inf')
            return slope1 == slope2

        p1, p2, p3 = points
        # 如果三个点中有任意两个点重合,它们不构成回旋镖
        if p1 == p2 or p1 == p3 or p2 == p3:
            return False
        # 如果三个点共线,它们也不构成回旋镖
        return not isCollinear(p1, p2, p3)

Explore

使用斜率来判断三点共线是一种直观且计算简单的方法。斜率作为直线的基本属性,可以有效地通过比较两条线段的斜率来确定它们是否共线。虽然使用面积(如通过判断三点构成的三角形的面积是否为零)也是一个可行的方法,但计算斜率通常在代码实现上更为直接和简洁。此外,在某些情况下,基于面积的方法可能需要处理更复杂的数值运算,例如使用行列式或者交叉乘积,这可能增加实现的复杂度和计算的误差。

在计算斜率时,直接使用除法可能导致除零错误,特别是当两点的x坐标相同时。在题解中,这种情况通过将斜率设为float('inf')来处理,从而避免了除零错误。然而,这种处理方式只在比较斜率时有效。如果需要进行其他数学运算,这种方法可能不适用。更稳妥的方法是使用条件语句检查分母是否为零,或使用乘法形式的斜率比较来避免除法的直接使用。

当使用浮点数坐标时,计算斜率并直接比较可能会遇到精度问题,因为浮点数运算可能不是完全精确的,容易引入微小的误差。这些误差在比较斜率时可能导致错误的判断(例如,本应相等的斜率被认为不相等)。为了减少这种误差,可以考虑使用其他数学方法比如epsilon容差来比较浮点数,或者转而使用整数运算,例如通过比较交叉乘积而不是直接比较斜率。

将斜率设为float('inf')是处理垂直线段的一种方法,因为垂直线段的斜率理论上是无限大。然而,使用float('inf')可以带来潜在的问题,例如在与其他斜率值进行比较时可能不会按预期工作,因为浮点数的比较可能不完全可靠。此外,如果斜率的计算或比较在更大的数学运算或算法中使用,使用float('inf')可能会引入不可预见的行为。更稳健的方法可能包括使用额外的逻辑标记来处理垂直线段的情况,而不是赋予斜率一个实际的数值。