LeetCode 447. Number of Boomerangs

189 篇文章 0 订阅
162 篇文章 0 订阅

Given n points in the plane that are all pairwise distinct, a "boomerang" is a tuple of points (i, j, k) such that the distance between i and j equals the distance between i and k (the order of the tuple matters).

Find the number of boomerangs. You may assume that n will be at most 500 and coordinates of points are all in the range [-10000, 10000] (inclusive).

Example:

Input:
[[0,0],[1,0],[2,0]]

Output:
2

Explanation:
The two boomerangs are [[1,0],[0,0],[2,0]] and [[1,0],[2,0],[0,0]]

 

 

 

扫描所有到i距离相等的点,如果有1个点,那么无法找到两个相同的点,如果有2个点到该点距离相等,那么可以找到其它两个点到i有相同的距离,那么选择这两个点的方式有多少种呢?第一次,可以在这两个点种任意选择一个,有两种选择方式,第二次再次选择,就只有一种选择方式了。所以,2*1=2有2种选择方式。同理,如果有3个点,有3*2=6种可能。

 

注:

boomerangs:回飞镖(boomerang的名词复数);自作自受,伤及原提案者的言论及提议。(计划)产生事与愿违的结果(boomerang的第三人称订单数),自食其果

plane:平面

pairwise:成对(双)地,两个两个地

distinct:adj,明显的,清楚的,卓越的,不寻常的,有区别的,确切的

tuple:元组,数组

虽然这些点都是整形,但是两点之间的距离有可能是一个浮点型,由于浮点型有浮点的误差,所以在查找表中进行查找的时候其实是不安全的。我们希望尽量不要有浮点型的误差,那怎么办呢?计算两点之间的距离是(x0-x1)的平方加上(y0-y1)的平方之和再开方,由于开根号产生了浮点数,所以进行查找表时完全可以不开根号。那么不开根号表示的就是距离的平方,虽然距离的平方反应的不是两点的真实距离,但是依然可以反应两个点之间的距离大小。换句话说,如果两点之间的距离相等的话,那么距离的平方一定也相等。这样,两点的距离是整型值,在查找表中查找就不会有误差的问题了。

 

对所有的点都进行了遍历,让所有的点都为枢纽点,之后又进行了遍历,计算其它的点到这个点的距离,之后遍历这个距离的值,来求出结果。外层是一次循环,内层有两次循环,那么整体是O(n²)级别的。对于空间来说,这个空间复杂度其实是O(n)级别的,因为对每一个枢纽都开了一个查找表,一旦这个枢纽表查找完之后,这个空间就释放掉了,虽然做了多个查找表,但是整体只额外多占了n这么一个空间,所以整体是O(n)的复杂度。在求dis()的时候,一个整数与另一个整数相乘,很容易出现整型越界的问题,所以需要明确,需要返回int还是返回long。而题目规定点的范围是[-1000,10000]之间,根据这个可以计算两点之间最大的距离是多少,即dis中最大为20000²+20000²,这样一个距离是没有超过32位这样一个范围的。所以,对于这道题来说是安全的,但是其它情况下可能会超过这个范围,此时,在具体实现的时候需要注意一下。

 

 

方法一:

时间复杂度:O(n²)

空间复杂度:O(n)

class Solution {
    public int numberOfBoomerangs(int[][] points) {
        if(points.length==0)return 0;
        int res=0;
        for(int i=0;i<points.length;i++){
            Map<Integer,Integer> map=new HashMap();
            for(int j=0;j<points.length;j++){
                if(i!=j){
                    int distance=distance(points[i],points[j]);
                    if(map.get(distance)!=null){
                        map.put(distance,map.get(distance)+1);
                    }else{
                        map.put(distance,1);
                    }
                }
            }
            
            for(int freq:map.values()){
                if(freq>=2)
                    res+=freq*(freq-1);
            }
        }
        return res;
    }
    
    private int distance(int[]a,int[] b){
        return (b[0]-a[0])*(b[0]-a[0])+(b[1]-a[1])*(b[1]-a[1]);
    }
}

 

 

方法二:

当距离某点相等的点的个数大于等于2时,就可以有得到结果值。

因为有顺序的区别,所以每增加一个点,结果数增加2倍

class Solution {
    public int numberOfBoomerangs(int[][] points) {
        if(points.length==0)return 0;
        int res=0;
 
        for(int i=0;i<points.length;i++){
            Map<Integer,Integer> map=new HashMap();
            for(int j=0;j<points.length;j++){
                int distance=distance(points[i],points[j]);
                Integer val=map.get(distance);
                if(map.containsKey(distance)){
                    res+=2*val;
                    map.put(distance,val+1);
                }else{
                    map.put(distance,1);
                }
            }
        }
        
        return res;
    }
    
    private int distance(int[]a,int[] b){
        return (int)(Math.pow(b[0]-a[0],2)+Math.pow(b[1]-a[1],2));
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值