Coding Interview Questions | K Closest Points to Origin
January 8th, 2024
K Closest Points to Origin Problem Introduction:
This summary will talk about my solution to the K closest points to the origin problem as seen on leetcode here.
How do you solve the K Closest Points to the Origin Problem in O(n) time?:
Solution:
type PointDistance = {
distance: number;
idx: number;
};
class MinHeap {
private heap: PointDistance[] = [];
private heapify(): void {
const n = this.heap.length;
// Start from the last non-leaf node and move up
for (let i = Math.floor(n / 2) - 1; i >= 0; i--) {
this.heapifyDown(i);
}
}
buildHeap(values: PointDistance[]): void {
this.heap = values;
this.heapify();
}
private swap(index1: number, index2: number): void {
[this.heap[index1], this.heap[index2]] = [
this.heap[index2],
this.heap[index1],
];
}
private getParentIndex(index: number): number {
return Math.floor((index - 1) / 2);
}
private getLeftChildIndex(index: number): number {
return 2 * index + 1;
}
private getRightChildIndex(index: number): number {
return 2 * index + 2;
}
private heapifyUp(): void {
let currentIndex = this.heap.length - 1;
while (currentIndex > 0) {
const parentIndex = this.getParentIndex(currentIndex);
if (this.heap[parentIndex].distance > this.heap[currentIndex].distance) {
this.swap(parentIndex, currentIndex);
currentIndex = parentIndex;
} else {
break;
}
}
}
private heapifyDown(idx?: number): void {
let currentIndex = idx ? idx : 0;
while (true) {
const leftChildIndex = this.getLeftChildIndex(currentIndex);
const rightChildIndex = this.getRightChildIndex(currentIndex);
let smallestChildIndex = null;
if (
leftChildIndex < this.heap.length &&
this.heap[leftChildIndex].distance < this.heap[currentIndex].distance
) {
smallestChildIndex = leftChildIndex;
}
if (
rightChildIndex < this.heap.length &&
this.heap[rightChildIndex].distance < this.heap[currentIndex].distance
) {
smallestChildIndex =
this.heap[rightChildIndex].distance <
this.heap[leftChildIndex].distance
? rightChildIndex
: smallestChildIndex;
}
if (smallestChildIndex === null) {
break;
}
this.swap(currentIndex, smallestChildIndex);
currentIndex = smallestChildIndex;
}
}
insert(value: PointDistance): void {
this.heap.push(value);
this.heapifyUp();
}
extractMin(): PointDistance | undefined {
if (this.heap.length === 0) {
return undefined;
}
if (this.heap.length === 1) {
return this.heap.pop()!;
}
const min = this.heap[0];
this.heap[0] = this.heap.pop()!;
this.heapifyDown();
return min;
}
peekMin(): PointDistance | undefined {
return this.heap.length > 0 ? this.heap[0] : undefined;
}
size(): number {
return this.heap.length;
}
isEmpty(): boolean {
return this.heap.length === 0;
}
}
function kClosest(points: number[][], k: number): number[][] {
// Loop through once, calculating distance to origin for each point using c = sqrt(a2 + b2), populating a distances array
// [[1, 1], [1,2]] -> [s2, s5]
// create min heap?
const distances = points.map((point, idx) => {
return { distance: point[0] ** 2 + point[1] ** 2, idx };
});
const minDistancesHeap = new MinHeap();
minDistancesHeap.buildHeap(distances);
const kClosestPoints: number[][] = [];
for (let i = 0; i < k; i++) {
const currentMin = minDistancesHeap.extractMin()!;
kClosestPoints.push(points[currentMin.idx]);
}
return kClosestPoints;
}
K Closest Points Solution Summary:
Below is a breakdown of the key aspects of the solution above:
-
Min Heap Construction: The
MinHeap
class is implemented with methods for heap construction, includingheapifyUp
,heapifyDown
, andbuildHeap
to efficiently manage a heap ofPointDistance
objects. -
Distance Calculation: The solution calculates the distance to the origin for each point using the Euclidean distance formula
sqrt(a^2 + b^2)
and populates adistances
array with{distance, idx}
objects. -
Min Heap Usage: The distances array is used to construct a min heap using the
MinHeap
class, ensuring quick retrieval of the k closest points. -
K Closest Points Extraction: The algorithm then iteratively extracts the minimum distance point from the min heap and appends the corresponding point from the original array to the result array
kClosestPoints
.
Complexities
- Time Complexity: The time complexity of the solution is
O(n + k log n)
, wheren
is the number of points. Constructing the distances array takesO(n)
time, and building the min heap and extracting the k closest points takesO(k log n)
time. Ifk
<<n
, the overall time complexity becomesO(n)
. - Space Complexity: The space complexity is
O(n)
due to the distances array and the min heap.