Question : Nearest Neighbour
Suboptimal Solution : Using Heap
Code :
public static List<List<int>> nearest_neighbours(int p_x, int p_y,
int k, List<List<int>> n_points) {
PriorityQueue<List<int>, double> queue = new
PriorityQueue<List<int>, double>();
foreach(var point in n_points) {
int x = point[0];
int y = point[1];
double distance = Math.Sqrt(Math.Pow(x - p_x, 2) + Math.Pow(y
- p_y, 2));
queue.Enqueue(point, distance);
}
List<List<int>> kthPoints = new List<List<int>>();
while(k > 0) {
kthPoints.Add(queue.Dequeue());
k--;
}
return kthPoints;
}
Optimal Solution : Using 3-way Quick Select
Code :
public static List<List<int>> nearest_neighbours(int p_x, int p_y, int k,
List<List<int>> n_points) {
// Write your code here.
Func<List<int>, double> distance = point =>
Math.Sqrt(Math.Pow(point[0] - p_x, 2) + Math.Pow(point[1] - p_y, 2));
// Quick select function
void QuickSelect(int left, int right, int kSmallest) {
if (left >= right)
return;
// Randomly shuffle the array to reduce average case time
Random random = new Random();
int randomPivot = random.Next(left, right + 1);
Swap(n_points, right, randomPivot);
// 3-way partition
int[] partitions = Partition(left, right);
int lt = partitions[0];
int gt = partitions[1];
if (kSmallest < lt)
QuickSelect(left, lt - 1, kSmallest);
else if (kSmallest > gt)
QuickSelect(gt + 1, right, kSmallest);
}
// Partition function
int[] Partition(int left, int right) {
double pivotDistance = distance(n_points[right]);
int lt = left;
int gt = right;
int i = left;
while (i <= gt) {
double currentDistance = distance(n_points[i]);
if (currentDistance < pivotDistance) {
Swap(n_points, lt, i);
lt++;
i++;
}
else if (currentDistance > pivotDistance) {
Swap(n_points, i, gt);
gt--;
}
else {
i++;
}
}
return new int[] { lt, gt };
}
// Helper function to swap elements in the list
void Swap(List<List<int>> list, int i, int j) {
List<int> temp = list[i];
list[i] = list[j];
list[j] = temp;
}
QuickSelect(0, n_points.Count - 1, k);
return n_points.GetRange(0, k);
}