You are given an 2-D array points where points[i] = [xi, yi] represents the coordinates of a point on an X-Y axis plane. You are also given an integer k.
Return the k closest points to the origin (0, 0).
The distance between two points is defined as the Euclidean distance (sqrt((x1 - x2)^2 + (y1 - y2)^2)).
You may return the answer in any order.
Example 1:
Input: points = [[0,2],[2,2]], k = 1
Output: [[0,2]]Explanation : The distance between (0, 2) and the origin (0, 0) is 2. The distance between (2, 2) and the origin is sqrt(2^2 + 2^2) = 2.82842. So the closest point to the origin is (0, 2).
Example 2:
Input: points = [[0,2],[2,0],[2,2]], k = 2
Output: [[0,2],[2,0]]Explanation: The output [2,0],[0,2] would also be accepted.
Constraints:
1 <= k <= points.length <= 1000-100 <= points[i][0], points[i][1] <= 100
You should aim for a solution as good or better than O(nlogk) time and O(k) space, where n is the size of the input array, and k is the number of points to be returned.
A naive solution would be to sort the array in ascending order based on the distances of the points from the origin (0, 0) and return the first k points. This would take O(nlogn) time. Can you think of a better way? Perhaps you could use a data structure that maintains only k points and allows efficient insertion and removal.
We can use a Max-Heap that keeps the maximum element at its top and allows retrieval in O(1) time. This data structure is ideal because we need to return the k closest points to the origin. By maintaining only k points in the heap, we can efficiently remove the farthest point when the size exceeds k. How would you implement this?
We initialize a Max-Heap that orders points based on their distances from the origin. Starting with an empty heap, we iterate through the array of points, inserting each point into the heap. If the size of the heap exceeds k, we remove the farthest point (the maximum element in the heap). After completing the iteration, the heap will contain the k closest points to the origin. Finally, we convert the heap into an array and return it.
Before attempting this problem, you should be comfortable with:
To find the k closest points to the origin (0, 0), we compare points by their distance from the origin.
Since the actual distance uses a square root, and square root preserves ordering, we can instead compare using squared distance:
[
d^2 = x^2 + y^2
]
This avoids unnecessary computation and is sufficient for sorting.
If we sort all points by this squared distance, then the first k points in sorted order must be the k closest ones.
(x, y), compute its squared distance: dist = x^2 + y^2dist value.k points from the sorted list.A min-heap always gives you the smallest element first.
If we insert every point into a min-heap, using its squared distance from the origin as the priority, then:
So if we remove from the heap k times, we get exactly the k closest points.
This works because the heap always keeps the smallest distances at the front.
(x, y):x^2 + y^2.(distance, x, y) into the heap.k times:(x, y) coordinates to the result.k closest points.class Solution:
def kClosest(self, points: List[List[int]], k: int) -> List[List[int]]:
minHeap = []
for x, y in points:
dist = (x ** 2) + (y ** 2)
minHeap.append([dist, x, y])
heapq.heapify(minHeap)
res = []
while k > 0:
dist, x, y = heapq.heappop(minHeap)
res.append([x, y])
k -= 1
return resWhere is the length of the array .
We want the k closest points, not all points sorted.
Use a max-heap of size k:
k closest points found so far.k sits at the top.This way, the heap never grows beyond size k, and it always contains the k best candidates.
d = x^2 + y^2.(d, point) into the heap.k:k closest points.class Solution:
def kClosest(self, points: List[List[int]], k: int) -> List[List[int]]:
maxHeap = []
for x, y in points:
dist = -(x ** 2 + y ** 2)
heapq.heappush(maxHeap, [dist, x, y])
if len(maxHeap) > k:
heapq.heappop(maxHeap)
res = []
while maxHeap:
dist, x, y = heapq.heappop(maxHeap)
res.append([x, y])
return resWhere is the length of the array .
We want the k closest points, but we do NOT need them sorted.
This is a perfect use-case for QuickSelect, the same idea used in QuickSort's partition step:
p:p == k, then the left side already contains the k closest points.p < k, search the right half.p > k, search the left half.This avoids fully sorting the array and runs in average O(N) time.
dist = x^2 + y^2.L = 0, R = n - 1.p == k, stop.p < k, move L = p + 1.p > k, move R = p - 1.k points in the array are the k closest.k points.class Solution:
def kClosest(self, points, k):
euclidean = lambda x: x[0] ** 2 + x[1] ** 2
def partition(l, r):
pivotIdx = r
pivotDist = euclidean(points[pivotIdx])
i = l
for j in range(l, r):
if euclidean(points[j]) <= pivotDist:
points[i], points[j] = points[j], points[i]
i += 1
points[i], points[r] = points[r], points[i]
return i
L, R = 0, len(points) - 1
pivot = len(points)
while pivot != k:
pivot = partition(L, R)
if pivot < k:
L = pivot + 1
else:
R = pivot - 1
return points[:k]Using sqrt(x^2 + y^2) is unnecessary and introduces floating-point precision issues. Since we only compare relative distances, squared distance x^2 + y^2 preserves ordering and avoids costly square root operations.
For the heap approach, using a min-heap requires extracting k elements at the end, while a max-heap of size k naturally keeps the k closest. Mixing these up leads to incorrect results or inefficient solutions that maintain more elements than needed.
When coordinates can be large (up to 10^4), squaring them produces values up to 10^8. While this fits in a 32-bit integer, summing two such values approaches the limit. In languages with overflow concerns, ensure your distance calculation uses appropriate integer types.