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));
}
}