《LeetCode之每日一题》:148.回旋镖的数量

回旋镖的数量


题目链接: 回旋镖的数量

有关题目

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

题解

Tips

①
	C++ 11原本的auto 写法 for(auto & j : cnt),然后下方使用 j.first,j.second。
	
	C++17的写法改成,可以直接取 map 里面 [v1, v2] 充当 j.first 及 j.second,
	如果下方不需要读值则可以用_代替
②
  auto&auto &&的区别 
	&为引用,相当于C中的指针,拿到所引用数据的地址,
	
	&&为右值引用,右值可以看作程序运行中的临时结果,直接引用返回的对象,避免了对象复制,从而提高效率。

法一:枚举 + 哈希表
参考官方题解

思路:
对于点points[i],有 m 个点到其距离相等,结合排列数的知识
我们需要从中选取两个,故有 A(2,m) = m * (m - 1)中组合

我们使用哈希表键存储距离的平方,值存储 m 个点,
对于每一个点points[i],我们更新一次答案,直至枚举一遍数组
class Solution {
public:
    int numberOfBoomerangs(vector<vector<int>>& points) {
        int ans = 0;
        for (auto& p : points){
            unordered_map<int, int> mp;
            for (auto& p1 : points){
                int squareOfDistance = (p[0] - p1[0]) * (p[0] - p1[0]) +
                    (p[1] - p1[1]) * (p[1] - p1[1]);
                ++mp[squareOfDistance];
            }
            for (auto& [_, m] : mp){
                ans += m * (m - 1);//排列数A(2,m) = m * (m - 1);
            }
        }
        return ans;
    }
};

时间复杂度:O(n^2),n 为points数组的长度
空间复杂度:O(n),哈希表存储所需O(n)复杂度

法二:优化法一
参考官方题解评论区下梦璃夜·天星

空间优化,少一次遍历。

利用排列组合中,每次多一个点,该点和前面每个点各有两个新的组合。
class Solution {
public:
    int numberOfBoomerangs(vector<vector<int>>& points) {
        int ans = 0;
        unordered_map<int, int> mp;
        for (auto&& p1 : points){
            mp.clear();
            for (auto&& p2 : points){
                int dis = (p1[0] - p2[0]) * (p1[0] - p2[0]) + 
                    (p1[1] - p2[1]) * (p1[1] - p2[1]);
                ans += 2 * mp[dis]++;
            }
        }
        return ans;
    }
};

时间复杂度:O(n^2),n 为points数组的长度
空间复杂度:O(n)

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值