Number of Boomerangs
You are given points on a plane, each written as a pair [x, y]. A boomerang is an ordered group of three different points (i, j, k) where the distance from i to j equals the distance from i to k. Return how many boomerangs there are. The group is ordered , so (i, j, k) and (i, k, j) count as two different boomerangs. Pick each point in turn as the middle point i, then count how many of the other points sit at each distance using a hash map from distance to tally. If d points share a distance, they give d times (d - 1) ordered pairs, because you choose one for j and a different one for k.
Constraints
- n == points.length, 1 ≤ n ≤ 500
- pointsi.length == 2
- -104 ≤ x, y ≤ 104
- All points are different
Example
points = [[0, 0], [1, 0], [2, 0]]2Explanation With [1, 0] as the anchor, both [0, 0] and [2, 0] sit at distance 1. That gives the two boomerangs ([1,0], [0,0], [2,0]) and ([1,0], [2,0], [0,0]).
In plain terms
- Squared distance
- The horizontal gap times itself plus the vertical gap times itself. It is used as the map key because it avoids square roots and rounding, and equal squared distances mean equal real distances.
- Ordered pair
- A pair where swapping the two items gives a different answer. With d points at the same distance there are d times (d - 1) ordered pairs of them.
- Anchor point
- The point in the middle of a boomerang, the one both distances are measured from. Every point takes a turn as the anchor.
One cell per distance key for the current anchor, plus the running total
Three points in a line, and no boomerangs counted yet.
What happens in this step
points = [[0,0], [1,0], [2,0]] total = 0 The first three cells will hold distance keys for one anchor at a time. The last cell keeps the running total.
Steps to visualize
- The first three cells are the keys of the distance map for the anchor being worked on right now.
- The label is the squared distance and the value is how many points sit that far away.
- The last cell is the running total of boomerangs found so far.
- The map is emptied each time a new anchor is picked.
- Each tally of d adds d times (d - 1) to the total.
Walk through the code
Same walkthrough, now with the code. Press Next to move one step and watch which lines run.
Three points in a line, and no boomerangs counted yet.
What happens in this step
points = [[0,0], [1,0], [2,0]] total = 0 The first three cells will hold distance keys for one anchor at a time. The last cell keeps the running total.
Solution
function numberOfBoomerangs(points) {
let total = 0;
for (const anchor of points) {
const distances = new Map();
for (const other of points) {
const dx = anchor[0] - other[0];
const dy = anchor[1] - other[1];
const distance = dx * dx + dy * dy;
distances.set(distance, (distances.get(distance) || 0) + 1);
}
for (const count of distances.values()) {
total += count * (count - 1);
}
}
return total;
}- Time
- O(n^2)
- Space
- O(n)
Test cases
| Input | Expected | Covers |
|---|---|---|
points = [[0, 0], [1, 0], [2, 0]] | 2 | example from the description |
points = [[1, 1], [2, 2], [3, 3]] | 2 | points evenly spaced along a diagonal |
points = [[1, 1]] | 0 | too few points to form any boomerang |
points = [[0, 0], [5, 5]] | 0 | a boomerang needs three points |
points = [[0, 0], [1, 0], [-1, 0], [0, 1], [0, -1]] | 20 | a centre point with four neighbours all at the same distance |
points = [[0, 0], [1, 0], [4, 0]] | 0 | no anchor has two neighbours at a matching distance |