K Closest Points to Origin is a classic "top-k" problem. It teaches two reusable moves: scoring items by a cheap comparable key, and using a heap to pull out the smallest few without sorting everything.
Problem. Given an array of points where points[i] = [x, y], and an integer k, return the k
points closest to the origin (0, 0). Distance is the usual Euclidean distance. The answer may be in any
order.
Example: points = [[1, 3], [-2, 2]], k = 1 → answer [[-2, 2]] (its distance 8 beats 10).
The slow way first
The obvious idea: compute every distance, sort all the points by distance, then take the first k. That works and is simple, but sorting costs O(n log n) even when k is tiny. If you only need the 3 closest out of a million points, sorting all million is wasteful.
The question to ask: do I really need the whole array ordered? No — I only need the k smallest. A heap gives me exactly that.
The idea: score, then heap
First, a trick that simplifies everything: distance is √(x² + y²), but the square root is monotonic — it never changes which point is closer. So we compare x² + y² directly and skip the sqrt entirely (also avoiding floating point).
Then push every (dist, point) onto a min-heap and pop k times. Each pop hands back the smallest remaining distance, so the first k pops are the k closest points.
The key insight: we never need a true distance, only a comparable score. Squared distance is cheaper and orders points identically.
Walk through it
Step through the animation. We score each point: [1, 3] gives 1 + 9 = 10, and [-2, 2] gives 4 + 4 = 8. Both go onto the min-heap. Since k = 1, we pop once and get the smallest distance, 8, which belongs to [-2, 2] — the answer.
Pseudocode
heap = empty min-heap
for each point (x, y):
dist = x*x + y*y # squared distance, no sqrt needed
push (dist, point) onto heap
result = empty list
repeat k times:
pop the smallest (dist, point) off the heap
add point to result
return resultThe Python solution
def k_closest(points, k):
heap = []
for x, y in points:
dist = x * x + y * y
heapq.heappush(heap, (dist, [x, y]))
result = []
for _ in range(k):
_, point = heapq.heappop(heap)
result.append(point)
return resultdist = x * x + y * yis the squared distance — comparable to a true distance but cheaper.heapqis Python's binary min-heap; pushing a(dist, point)tuple orders entries bydistfirst.- The first loop builds the heap in O(n log n) (or O(n) with
heapify). - The second loop pops
ktimes; each pop is O(log n) and returns the next-smallest distance. - We collect
kpoints and return them — thekclosest to the origin.
Complexity
| Case | Time | Notes |
|---|---|---|
| Sort everything | O(n log n) (moderate) | orders all points, even unused ones |
| Heap (this solution) | O(n log n) (moderate) | push n, then pop k; great when k is small |
| Quickselect (advanced) | O(n) average (moderate) | partition around the k-th distance |
O(n) (moderate)For small k, a smarter variant keeps a max-heap of size k: push each point and, if the heap grows past k, pop the farthest. That bounds the heap to k entries and runs in O(n log k).
When this pattern shows up
Any "k closest / k largest / k most frequent / top-k" problem is a heap problem. Score each item by a comparable key, then let a heap of size k surface the answers without a full sort.
Do not compute the actual √ distance. It adds cost and floating-point error for zero benefit — the
ordering of x² + y² is identical, so always compare the squared distance.
Practice
For points = [[1, 3], [-2, 2]] with k = 1, what squared distance does each point get, and which is returned?
1. Why do we compare x² + y² instead of the real distance √(x² + y²)?
2. Why use a heap instead of sorting all the points?
3. For points = [[1, 3], [-2, 2]], k = 1, what is returned?
4. What is the space complexity of pushing every point onto the heap?