📜  共n个点,m个共线的三角形的计数(1)

📅  最后修改于: 2023-12-03 15:07:04.710000             🧑  作者: Mango

计算共线三角形的数量

给定平面上的 $n$ 个点,求其中共线的三元组 $(i, j, k)$ 的数量,满足 $1 \leq i < j < k \leq n$。

算法

该问题可以通过枚举所有可能的三元组 $(i, j, k)$ 并判断它们是否共线,但这样计算的时间复杂度为 $O(n^3)$,无法通过本题。

可以考虑一种更有效的方法。我们首先枚举所有的点对 $(i, j)$,并计算出它们的斜率 $k_{ij}$。对于每一个斜率,我们可以记录对应的点 $i$ 和 $j$ 的个数 $cnt_{ij}$。注意到斜率不存在或者两个点在 $x$ 轴上的情况,需要特殊处理。

然后,对于每一个点 $k$,我们枚举所有与点 $k$ 组成的点对 $(i, j)$,并根据它们的斜率是否与点 $k$ 和 $(i, j)$ 的斜率相同,来判断是否有共线三元组。具体来说,设点 $i$ 和点 $j$ 在点 $k$ 的斜率为 $k_{ik}$ 和 $k_{jk}$,则点 $i,j,k$ 共线当且仅当 $k_{ik}=k_{jk}=k_{ij}$。注意到同一个点 $k$ 可能会被多个点对所包含,所以需要乘上对应的 $cnt_{ij}$。

时间复杂度为 $O(n^2)$。由于点对数量为 $O(n^2)$,所以空间复杂度为 $O(n^2)$。

代码
def count_collinear(n: int, points: List[Tuple[int, int]]) -> int:
    cnt = defaultdict(int)
    for i in range(n):
        for j in range(i + 1, n):
            if points[j][0] == points[i][0]:
                slope = float('inf')
            else:
                slope = (points[j][1] - points[i][1]) / (points[j][0] - points[i][0])
            cnt[(slope, points[i][0], points[j][0])] += 1

    ans = 0
    for k in range(n):
        for i in range(k):
            if points[i][0] == points[k][0]:
                slope1 = float('inf')
            else:
                slope1 = (points[i][1] - points[k][1]) / (points[i][0] - points[k][0])
            for j in range(i + 1, k):
                if points[j][0] == points[k][0]:
                    slope2 = float('inf')
                else:
                    slope2 = (points[j][1] - points[k][1]) / (points[j][0] - points[k][0])
                ans += cnt[(slope1, points[k][0], points[i][0])] * cnt[(slope2, points[k][0], points[j][0])]
                ans += cnt[(slope1, points[k][0], points[j][0])] * cnt[(slope2, points[k][0], points[i][0])]
    return ans
参考文献