The "Number of Boomerangs" problem asks you to count the number of boomerang tuples in a set of distinct points on a 2D plane. A boomerang is defined as a tuple of points (i, j, k) such that the distance between point i and point j is equal to the distance between point i and point k. The order of the tuple matters, so (i, j, k) is considered different from (i, k, j).
[x, y].i, j, and k are all different).
Let's start by understanding what a boomerang is in this context. For every point i, we want to find all pairs of points (j, k) such that distance(i, j) == distance(i, k) and j != k. Since the order matters, both (i, j, k) and (i, k, j) are counted as separate boomerangs.
The brute-force approach would be to check all possible ordered triplets, but this would be very slow for large inputs. To optimize, we can focus on each point i and count, for each possible distance, how many points are at that distance from i. If there are n points at the same distance from i, then there are n * (n - 1) possible boomerang tuples for that distance (since order matters).
This shift—from checking every triplet to grouping points by distance from a fixed center—makes the solution much more efficient.
Here’s how we can solve the problem step-by-step:
i of a boomerang:
i, we want to find out how many other points are the same distance away from i.j, compute the squared Euclidean distance from i to j (we can use squared distance to avoid floating-point errors and it's sufficient for comparison).n points at a particular distance from i, then the number of ordered pairs is n * (n - 1).i and sum the results.
We use a hash map because it allows us to count distances in O(1) time, making the approach efficient.
Let's use the input points = [[0,0], [1,0], [2,0]] as an example.
[0,0]:
[1,0]: 1[2,0]: 4[1,0]:
[0,0]: 1[2,0]: 1[2,0]:
[0,0]: 4[1,0]: 1This matches the expected output.
i, we compute distances to all other points: O(n) per point.The problem can be solved efficiently by focusing on each point as the center and counting how many other points are at the same distance from it. Using a hash map to group points by distance allows us to quickly calculate the number of boomerang tuples in O(n²) time. This approach is far more efficient than brute-force checking of all triplets, and the use of squared distances avoids precision issues. The strategy elegantly leverages counting and combinatorics to produce the correct answer.
class Solution:
def numberOfBoomerangs(self, points):
res = 0
for i in points:
dist_map = {}
for j in points:
if i == j:
continue
dx = i[0] - j[0]
dy = i[1] - j[1]
dist = dx * dx + dy * dy
dist_map[dist] = dist_map.get(dist, 0) + 1
for count in dist_map.values():
res += count * (count - 1)
return res
class Solution {
public:
int numberOfBoomerangs(vector<vector<int>>& points) {
int res = 0;
for (auto& i : points) {
unordered_map<int, int> dist_map;
for (auto& j : points) {
if (i == j) continue;
int dx = i[0] - j[0];
int dy = i[1] - j[1];
int dist = dx * dx + dy * dy;
dist_map[dist]++;
}
for (auto& kv : dist_map) {
res += kv.second * (kv.second - 1);
}
}
return res;
}
};
class Solution {
public int numberOfBoomerangs(int[][] points) {
int res = 0;
for (int[] i : points) {
Map<Integer, Integer> distMap = new HashMap<>();
for (int[] j : points) {
if (i == j) continue;
int dx = i[0] - j[0];
int dy = i[1] - j[1];
int dist = dx * dx + dy * dy;
distMap.put(dist, distMap.getOrDefault(dist, 0) + 1);
}
for (int count : distMap.values()) {
res += count * (count - 1);
}
}
return res;
}
}
var numberOfBoomerangs = function(points) {
let res = 0;
for (let i of points) {
let distMap = new Map();
for (let j of points) {
if (i === j) continue;
let dx = i[0] - j[0];
let dy = i[1] - j[1];
let dist = dx * dx + dy * dy;
distMap.set(dist, (distMap.get(dist) || 0) + 1);
}
for (let count of distMap.values()) {
res += count * (count - 1);
}
}
return res;
};