回旋镖的数量

标签: 数组 哈希表 数学

难度: Medium

给定平面上 n 互不相同 的点 points ,其中 points[i] = [xi, yi]回旋镖 是由点 (i, j, k) 表示的元组 ,其中 i 和 j 之间的欧式距离和 i 和 k 之间的欧式距离相等(需要考虑元组的顺序)。

返回平面上所有回旋镖的数量。

 

示例 1:

输入:points = [[0,0],[1,0],[2,0]]
输出:2
解释:两个回旋镖为 [[1,0],[0,0],[2,0]][[1,0],[2,0],[0,0]]

示例 2:

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

示例 3:

输入:points = [[1,1]]
输出:0

提示:

  • n == points.length
  • 1 <= n <= 500
  • points[i].length == 2
  • -104 <= xi, yi <= 104
  • 所有点都 互不相同

Submission

运行时间: 256 ms

内存: 22.2 MB

class Solution:
  def numberOfBoomerangs(_, p):
    n = len(p)
    d2 = [[0]*n for i in range(n)]
    for i,(a,b) in enumerate(p):
      for j in range(i+1, n):
        d2[i][j] = d2[j][i] = (a-p[j][0])**2 + (b-p[j][1])**2
    return sum(b*(b-1) for b in chain.from_iterable(Counter(a).values() for a in d2) if b > 1)
      

Explain

这个题解的思路是先计算出所有点对之间的欧式距离的平方,存储在二维数组d2中。然后对于每个点,统计与其他点距离相等的点的个数,即可得到以该点为中心的回旋镖的数量。最后将所有点的回旋镖数量相加即可得到答案。

时间复杂度: O(n^2)

空间复杂度: O(n^2)

```python
class Solution:
  def numberOfBoomerangs(_, p):
    n = len(p)
    # 存储所有点对之间的欧式距离的平方
    d2 = [[0]*n for i in range(n)]
    for i,(a,b) in enumerate(p):
      for j in range(i+1, n):
        d2[i][j] = d2[j][i] = (a-p[j][0])**2 + (b-p[j][1])**2
    
    # 对于每个点,统计距离相等的点的个数,计算回旋镖的数量
    return sum(b*(b-1) for b in chain.from_iterable(Counter(a).values() for a in d2) if b > 1)
```

Explore

在Python中,整数类型(int)支持长整型,可以自动扩展以容纳大数值,因此通常不会因为整数过大而溢出。尽管如此,如果在其他编程语言中实现这一算法,需要考虑整数范围限制。可以通过使用更大的数据类型(如长整型)或增加额外的检查来防止溢出。例如,在C++中,可以在进行乘法操作前检查是否会超过整数的最大值。

存储欧式距离的平方而不是欧式距离本身主要有两个原因:首先,计算距离的平方可以避免涉及浮点运算,这样做可以减少计算误差并提高性能;其次,由于回旋镖问题只关心距离是否相等,而不关心距离的具体值,所以使用距离的平方可以简化计算过程,同时保持距离的唯一性。

Counter类是Python中collections模块提供的一个字典子类,它用于计数可哈希对象。在这个题解中,Counter被用于统计每个点与其他所有点之间的距离出现的次数。通过将距离作为键,出现次数作为值,可以快速统计任何给定距离的点的数量,进而计算出以每个点为顶点可以形成的回旋镖数量。

题解中通过一个双重循环实现了对数组d2的赋值。外层循环遍历每个点作为第一个点,内层循环从外层的当前点的下一个点开始,遍历所有其他点作为第二个点,这样确保了每一对点之间的距离被计算一次且仅一次。通过这种方式,每对点的距离被计算并存储在d2数组中,从而确保没有任何两点间的距离被遗漏。