给定平面上 n 对不同的点,“回旋镖” 是由点表示的元组 (i, j, k) ,其中 i 和 j 之间的距离和 i 和 k 之间的距离相等(需要考虑元组的顺序)。

找到所有回旋镖的数量。你可以假设 n 最大为 500,所有点的坐标在闭区间 [-10000, 10000] 中。

示例:

输入:[[0,0],[1,0],[2,0]]
输出:2
解释:两个回旋镖为 [[1,0],[0,0],[2,0]][[1,0],[2,0],[0,0]]

答案:

 1public int numberOfBoomerangs(int[][] points) {
2    int res = 0;
3    Map<Integer, Integer> map = new HashMap<>();
4    for (int i = 0; i < points.length; i++) {
5        for (int j = 0; j < points.length; j++) {
6            if (i == j)
7                continue;
8            int d = getDistance(points[i], points[j]);
9            map.put(d, map.getOrDefault(d, 0) + 1);
10        }
11        for (int val : map.values()) {
12            res += val * (val - 1);
13        }
14        map.clear();
15    }
16    return res;
17}
18
19private int getDistance(int[] a, int[] b) {
20    int dx = a[0] - b[0];
21    int dy = a[1] - b[1];
22    return dx * dx + dy * dy;
23}

解析:

这题的意思是平面上有n个点,随便找3个点(i,j,k)并且i到j的距离和i到k的距离相等。找出这样的3个点共有多少个。getDistance是求两点之间的距离的平方,这里没有开根号。上面题不太好理解的估计是res += val * (val - 1);这样一行代码。这行代码是放在第一个for循环中的,举个例子,比如第一次循环的时候,拿第一个点A和后面的所有点比较并计算距离,如果val等于1,说明到A点距离为val的只有1个,构不成回旋镖,所以val * (val - 1)等于0。如果val等于2的时候,说明有2个点到点A的距离相等,所以可以构成一个回旋镖,但因为有顺序的,可以调换位置,所以有两个。同样如果val为3的时候,可以构成3组,但每组又可以调换位置,所以有6个……。再来改一下

 1public int numberOfBoomerangs(int[][] points) {
2    int result = 0;
3    HashMap<Integer, Integer> distMap = new HashMap<>();
4    for (int[] i : points) {
5        for (int[] j : points) {
6            if (i == j) continue;
7            int dist = getDis(i, j);
8            int prevDist = distMap.getOrDefault(dist, 0);
9            distMap.put(dist, prevDist + 1);
10            result += prevDist << 1;
11        }
12        distMap.clear();
13    }
14    return result;
15}
16
17public int getDis(int[] p, int[] q) {
18    int a = p[0] - q[0];
19    int b = p[1] - q[1];
20    return a * a + b * b;
21}