Reputation: 2138
Source: AMAZON INTERVIEW QUESTION
Given a point P and other N points in two dimensional space, find K points out of the N points which are nearest to P.
What is the most optimal way to do this ?
This Wiki page does not provide much of help in building a algorithm.Any ideas/approaches people.
Upvotes: 26
Views: 36147
Reputation: 1170
C# Solution using LINQ
public int[][] KClosest(int[][] points, int[][] p, int K) {
var orderedPoints = points.OrderBy(point => Math.Pow(point[0]-p[0], 2) + Math.Pow(point[1]-p[1], 2));
return orderedPoints.Take(K).ToArray();
}
Upvotes: 0
Reputation: 1
public static void NearestPoints() {
int[][] Points = { new int[] { -16, 5 },
new int[] { -1, 2 },
new int[] { 4, 3 },
new int[] { 10, -2 },
new int[] { 0, 3 },
new int[] {- 5, -9 } };
// Linq Order by default use quick sort which will be best suited in this.
var orderPoint = from i in Enumerable.Range(0, Points.Length)
orderby Math.Sqrt( Points[i][0] * Points[i][0]
+ Points[i][1] * Points[i][1] )
select new int[][] { Points[i] };
var result = orderPoint.Take(3);
}
Upvotes: -2
Reputation: 93
class Solution {
public int[][] kClosest(int[][] points, int K) {
double [] combinationArr = new double[points.length];
Hashtable<Double,int[]> pt = new Hashtable();
for (int i = 0; i <points.length; i++) {
int [] in = points[i];
for (int j = 0; j < in.length - 1; j++) {
Integer x = in[j];
Integer y = in[j + 1];
double powerX=Math.pow(x, 2);
double powerY = Math.pow(y, 2);
double combination= (Double)(Math.sqrt(powerX + powerY));
pt.put(combination, points[i]);
combinationArr[i] = combination;
}
}
Arrays.sort(combinationArr);
int [][] kpoints = new int[K][K];
for (int n = 0; n < K; n++) {
kpoints[n] = pt.get(combinationArr[n]);
}
return kpoints;
}
}
Upvotes: 0
Reputation: 647
// point_type pt, length_sq(p) { return pt[0] * pt[0] + pt[1] * pt[1]}
// std::vector<point_type> points to search.
// The algorithm should recursion depth to
// O(k * log(points.size())), and
// running time to O(points.size()).
std::nth_element(
points.begin(),
points.begin() + k,
points.end(),
[&pt](point_type const & a)
{
return length_squared(a - pt);
});
// points[0], ... , points[k - 1] are the closest points to pt
Upvotes: 0
Reputation: 336
Solution 1
private List<Point> nearestKPoint_1(List<Point> list, final Point center, int k) {
List<Point> ans = new ArrayList<>();
PriorityQueue<Point> maxHeap = new PriorityQueue<>(k + 1, new Comparator<Point>() {
@Override
public int compare(Point o1, Point o2) {
return distance(center, o2) - distance(center, o1);
}
});
for (Point p : list) {
maxHeap.offer(p);
if (maxHeap.size() > k) {
maxHeap.poll();
}
}
Iterator<Point> i = maxHeap.iterator();
while (i.hasNext()) {
ans.add(i.next());
}
return ans;
}
public int distance(Point p1, Point p2) {
return (p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y);
}
static class Point {
int x;
int y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Point point = (Point) o;
if (x != point.x) return false;
return y == point.y;
}
@Override
public int hashCode() {
int result = x;
result = 31 * result + y;
return result;
}
}
Solution 2
private List<Point> nearestKPoint_2(List<Point> list, final Point center, int k) {
List<Point> ans = new ArrayList<>();
Distance[] nums = new Distance[list.size()];
for (int i = 0; i < nums.length; i++) {
nums[i] = new Distance(distance(center, list.get(i)), i);
}
quickSelect(nums, k);
for (int i = 0; i < k; i++) {
ans.add(list.get(nums[i].i));
}
return ans;
}
private void quickSelect(Distance[] nums, int k) {
int start = 0, end = nums.length - 1;
while (start < end) {
int p = partition(nums, start, end);
if (p == k) {
return;
} else if (p < k) {
start = p + 1;
} else {
end = p - 1;
}
}
}
private int partition(Distance[] nums, int start, int end) {
Distance pivot = nums[start];
int i = start, j = end + 1;
while (true) {
while (i < end && nums[++i].compareTo(pivot) < 0);
while (j > start && nums[--j].compareTo(pivot) > 0);
if (i >= j) {
break;
}
swap(nums, i, j);
}
swap(nums, start, j);
return j;
}
private void swap(Distance[] nums, int i, int j) {
Distance tmp = nums[i];
nums[i] = nums[j];
nums[j] = tmp;
}
class Distance implements Comparable<Distance> {
int d;
int i;
public Distance(int d, int i) {
this.d = d;
this.i = i;
}
@Override
public int compareTo(Distance o) {
return this.d - o.d;
}
}
Upvotes: 5
Reputation: 692
What is wrong with below approach ?
1) Calculate distance from given point to other points.
2) Store the distance and index of that point to TreeMap<Double,Integer> map
3) Select top K elements from map. It's values will give index of Point element from points array.
The map is sorted according to the natural ordering of its keys, or by a Comparator provided at map creation time,
Upvotes: -1
Reputation: 95
You could use KD tree http://en.wikipedia.org/wiki/K-d_tree to partition space and given the point you will be able to gradually search for neighbors using binary search. Benefit of using this approach is that it easily scales up to online version when you receive points/queries in runtime one by one or in batches.
Upvotes: 4
Reputation: 2857
Solution 1 make heap of size K and collect points by minimal distance O(NLogK) complexity.
Solution 2: Take and array of size N and Sort by distance. Should be used QuickSort (Hoare modification). As answer take first K points. This is too NlogN complexity but it is possible optimize to approximate O(N). If skip sorting of unnecessary sub arrays. When you split array by 2 sub arrays you should take only array where Kth index located. complexity will be : N +N/2 +N/4 + ... = O(N).
Solution 3: search Kth element in result array and takes all point lesser then founded. Exists O(N) alghoritm, similar to search of median.
Notes: better use sqr of distance to avoid of sqrt operations, it will be greater faster if point has integer coordinates.
As interview answer better use Solution 2 or 3.
Upvotes: 39
Reputation: 55609
For just a single query...
Maintain a heap of size k
.
For each point, calculate the distance to the point P
. Insert that distance into the heap and delete the maximum from the heap if the size of the heap is greater than k
.
Running time: O(n log k)
Upvotes: 8