0447-回旋镖的数量

Raphael Liu Lv10

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

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

示例 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
  • 所有点都 互不相同

方法一:枚举 + 哈希表

题目所描述的回旋镖可以视作一个 V 型的折线。我们可以枚举每个 points}[i]$,将其当作 V 型的拐点。设 points 中有 $m$ 个点到 points}[i]$ 的距离均相等,我们需要从这 $m$ 点中选出 $2$ 个点当作回旋镖的 $2$ 个端点,由于题目要求考虑元组的顺序,因此方案数即为在 $m$ 个元素中选出 $2$ 个不同元素的排列数,即:

$$
A_m^2 = m\cdot(m-1)
$$

据此,我们可以遍历 points,计算并统计所有点到 points}[i]$ 的距离,将每个距离的出现次数记录在哈希表中,然后遍历哈希表,并用上述公式计算并累加回旋镖的个数。

在代码实现时,我们可以直接保存距离的平方,避免复杂的开方运算。

[sol1-Python3]
1
2
3
4
5
6
7
8
9
10
11
class Solution:
def numberOfBoomerangs(self, points: List[List[int]]) -> int:
ans = 0
for p in points:
cnt = defaultdict(int)
for q in points:
dis = (p[0] - q[0]) * (p[0] - q[0]) + (p[1] - q[1]) * (p[1] - q[1])
cnt[dis] += 1
for m in cnt.values():
ans += m * (m - 1)
return ans
[sol1-C++]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Solution {
public:
int numberOfBoomerangs(vector<vector<int>> &points) {
int ans = 0;
for (auto &p : points) {
unordered_map<int, int> cnt;
for (auto &q : points) {
int dis = (p[0] - q[0]) * (p[0] - q[0]) + (p[1] - q[1]) * (p[1] - q[1]);
++cnt[dis];
}
for (auto &[_, m] : cnt) {
ans += m * (m - 1);
}
}
return ans;
}
};
[sol1-Java]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Solution {
public int numberOfBoomerangs(int[][] points) {
int ans = 0;
for (int[] p : points) {
Map<Integer, Integer> cnt = new HashMap<Integer, Integer>();
for (int[] q : points) {
int dis = (p[0] - q[0]) * (p[0] - q[0]) + (p[1] - q[1]) * (p[1] - q[1]);
cnt.put(dis, cnt.getOrDefault(dis, 0) + 1);
}
for (Map.Entry<Integer, Integer> entry : cnt.entrySet()) {
int m = entry.getValue();
ans += m * (m - 1);
}
}
return ans;
}
}
[sol1-C#]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class Solution {
public int NumberOfBoomerangs(int[][] points) {
int ans = 0;
foreach (int[] p in points) {
Dictionary<int, int> cnt = new Dictionary<int, int>();
foreach (int[] q in points) {
int dis = (p[0] - q[0]) * (p[0] - q[0]) + (p[1] - q[1]) * (p[1] - q[1]);
if (!cnt.ContainsKey(dis)) {
cnt.Add(dis, 1);
} else {
++cnt[dis];
}
}
foreach (KeyValuePair<int, int> kv in cnt) {
int m = kv.Value;
ans += m * (m - 1);
}
}
return ans;
}
}
[sol1-Golang]
1
2
3
4
5
6
7
8
9
10
11
12
13
func numberOfBoomerangs(points [][]int) (ans int) {
for _, p := range points {
cnt := map[int]int{}
for _, q := range points {
dis := (p[0]-q[0])*(p[0]-q[0]) + (p[1]-q[1])*(p[1]-q[1])
cnt[dis]++
}
for _, m := range cnt {
ans += m * (m - 1)
}
}
return
}
[sol1-JavaScript]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
var numberOfBoomerangs = function(points) {
let ans = 0;
for (const p of points) {
const cnt = new Map();
for (const q of points) {
const dis = (p[0] - q[0]) * (p[0] - q[0]) + (p[1] - q[1]) * (p[1] - q[1]);
cnt.set(dis, (cnt.get(dis) || 0) + 1);
}
for (const [_, m] of cnt.entries()) {
ans += m * (m - 1);
}
}
return ans;
};

复杂度分析

  • 时间复杂度:$O(n^2)$,其中 $n$ 是数组 points 的长度。

  • 空间复杂度:$O(n)$。

 Comments
On this page
0447-回旋镖的数量