一、题目描述
☆☆☆☆☆二、解法
思路:暴力解法是O(n^3)
观察到 i 是一个“枢纽”,对于每个点 i ,遍历其余的点到 i 的距离。 时间复杂度O(n^2),空间复杂度O(n)
使用Map,其键是距离,值是距离出现的频次。 例如,如果距离值 dis 对应的频次为1,那就无法找到两个点与 i 距离dis相等。
Note:由于把距离作为键,而计算距离开根号会出现浮点数,因此,可以用距离的平方代替。
class Solution { public int numberOfBoomerangs(int[][] points) { if (points == null || points.length < 3) return 0; /** * 写法1 */ /* int count = 0; Map<Integer,Integer> map = new HashMap<>(); // key/value => 距离/出现次数 for (int i = 0; i < points.length; i++) { // 每一个 i 都是一个枢纽点 for (int j = 0; j < points.length; j++) { if (j != i) { map.put(dis(points,i,j), map.getOrDefault(dis(points,i,j), 0) + 1); } } for (int d : map.keySet()) { if (map.get(d) > 1) { count += map.get(d) * (map.get(d) - 1); } } map.clear(); } return count; */ /** * 写法2:对上述代码进行优化 * 优化思路为:假设当前同一距离的数量为 n, 回旋镖数量为 n*(n-1), * 当再出现一个同一距离时,回旋镖的数量应为 (n+1)*n, * 与之前相差 (n+1)*n - n*(n-1) = 2*n, * 所以只需要把最后答案加上 2*n, 最后 n+1 再存储到哈希表中。 */ int count = 0; Map<Integer,Integer> map = new HashMap<>(); for (int i = 0; i < points.length; i++) { for (int j = 0; j < points.length; j++) { if (i != j) { int d = dis(points, i, j); if (!map.containsKey(d)) { map.put(d, 1); }else { int n = map.get(d); count += 2*n; map.put(d, n+1); } } } map.clear(); } return count; } // 计算两点距离的平方 private int dis(int[][] points, int i, int j) { return (points[i][0] - points[j][0]) * (points[i][0] - points[j][0]) + (points[i][1] - points[j][1]) * (points[i][1] - points[j][1]); } }