LeetCode: 447. 回旋镖的数量

600 阅读1分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第28天,点击查看活动详情

447. 回旋镖的数量

来源:力扣(LeetCode) 链接:leetcode-cn.com/problems/nu…

给定平面上 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-10^4 <= xi, yi <= 10410^4
  • 所有点都 互不相同

解法

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

Am2=m(m1)A_m^2 =m⋅(m−1)

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

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

  • python
from collections import defaultdict

class Solution:
    def numberOfBoomerangs(self, points: List[List[int]]) -> int:
        n = len(points)
        if n == 1:
            return 0
        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

  • c++
class Solution {
public:
    int numberOfBoomerangs(vector<vector<int>>& points) {
        int n = points.size();
        int ans = 0;
        if (n < 3)
        {
            return ans;
        }

        unordered_map<int, int> cnt;
        for (int i = 0; i < n; i++) 
        {
            cnt.clear();
            for(int j = 0; j < n; j++)
            {
                // if(i==j)
                //    continue;
                int dis = (points[i][0] - points[j][0]) * (points[i][0] - points[j][0]) + (points[i][1] - points[j][1]) * (points[i][1] - points[j][1]);
                cnt[dis]++;
            }
        for (auto p: cnt) 
        {
            ans += p.second * (p.second - 1);
        }
    }
    return ans;
    }
};

复杂度分析

  • 时间复杂度: O(n2)O(n^2), 两层循环

  • 空间复杂度: O(n)O(n), 哈希表存储