## Problem Statement

You are given millions of two dimensional point and a utility method to calculate their distances from the origin. Write a code to return the nearest K unique distances from the origin.

If there are more than one point at the same distance, the distance must be just returned once. For e.g. If there are five points (1,1), (2,1), (1,2), (2,2) and (3,3) and the value of K is 3, then we need to return the following:

- 1.414 – distance of (1,1) from origin.
- 2.236 – distance of (2,1) or (1,2) from origin as both will be same.
- 2.828 – distance of (2,2) from origin

### Test Cases

Here are few critical test scenarios which must be handled properly

- No points
- Points less than k
- Points more than k, but points with unique distance is less than k
- A lot of repeated points
- Millions of points

### Naive Approach for Finding K nearest distances

- Traverse through the list/array of points and add all of them to a Set (handling test case 4)
- Traverse through the set and add the distance of each point into another set (enabler for test case 3)
- Add all the distances from the set to a List (you can use sort function of the Collections framework on List not Set)
- If the size of the List is less than K, return the list (handling test cases 2 and 3)
- Else return a sub list of the List from index 0 to K

### Source Code

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
public static List<Double> nearestDistances(Point[] points, int k) { if (points == null || points.length == 0) return null; Set<Point> pointSet = new HashSet<Point>(); pointSet.addAll(Arrays.asList(points)); Set<Double> distances = new HashSet<Double>(); for (Point p : pointSet) { distances.add(Util.distFromOriginUtil(p)); } List<Double> distList = new ArrayList<Double>(); distList.addAll(distances); Collections.sort(distList); if (distList.size() > k) return distList.subList(0, k); else return distList; } |

The test case 5 is a bottleneck and if the number of points increase, it would be really tough to allocate that much of memory, consider billions or trillions of points. Creating auxiliary sets or arrays for distances would increase the space complexity. So, we need a different approach

### Heap based solution for Finding K nearest distances

- Create a MaxHeap
- Add first K unique distances into the Heap
- Iterate through the remaining points
- Calculate the distance of each point.
- If the distance is not added in the Heap and it is less than the max value in Heap, insert this value in the Heap and extract the max from the Heap. (This approach doesn’t require auxiliary memory more than size K.)
- Return the content of the Heap.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
public static double[] nearestDistanceHeap(Point[] points, int k) { if (points == null || points.length == 0) return null; MaxHeap H = new MaxHeap(); int insertCount = 0; int i = 0; do { double dist = Util.distFromOriginUtil(points[i++]); if (!H.find(dist, 0)) { try { H.insert(dist); insertCount++; } catch (Exception e) { e.printStackTrace(); } } } while (insertCount < k && i < points.length); for (i = k; i < points.length; i++) { double dist = Util.distFromOriginUtil(points[i]); if (dist < H.getMax()) { if (!H.find(dist, 0)) { try { H.insert(dist); H.extractMax(); } catch (Exception e) { e.printStackTrace(); } } } } return H.A; } |

To get the complete code, please visit the github link .

Please suggest more test cases so that it can help everyone who is preparing for an interview.

Stay connected and stay subscribed.