web-dev-qa-db-de.com

Finde K nächstgelegene Punkte zu Punkt P in der 2-dimensionalen Ebene

Quelle: Amazon INTERVIEW-FRAGE

Wenn ein Punkt P und andere N Punkte im zweidimensionalen Raum gegeben sind, finden Sie K Punkte aus den N Punkten, die am nächsten zu P. liegen.

Was ist der beste Weg, dies zu tun?

Diese Wiki Seite bietet keine große Hilfe beim Erstellen eines Algorithmus. Alle Ideen/Ansätze von Menschen.

18
Spandan

Lösung 1 Haufen von Größe K machen und Punkte mit minimalem Abstand sammeln O(NLogK) Komplexität.

Lösung 2 : Nehmen Sie ein Array der Größe N und sortieren Sie nach Entfernung. Sollte verwendet werden QuickSort (Hoare-Modifikation) . Als Antwort nehmen Sie zuerst K Punkte . Dies ist zu viel NlogN-Komplexität, aber es ist möglich zu optimieren, um O (N) ..__ zu approximieren. Wenn Sie ein Array in zwei Sub-Arrays aufteilen, sollten Sie nur ein Array verwenden, bei dem sich der K-te Index befindet. Die Komplexität ist: N + N/2 + N/4 + ... = O(N) .

Lösung 3 : Suchen Sie das Kth-Element im Ergebnis-Array und nimmt alle Punkte auf, die niedriger sind, als es gilt. Existiert O(N) alghoritm, ähnlich wie bei der Suche nach dem Median.

Hinweise : Um die sqrt-Operationen zu vermeiden, sollten Sie den Abstand von sqr verwenden. Er ist schneller, wenn der Punkt ganzzahlige Koordinaten hat.

Als Antwort auf das Interview besser Lösung 2 oder 3 verwenden.

31
Толя

Für nur eine einzige Abfrage ...

Pflegen Sie einen Heap der Größe k.

Berechnen Sie für jeden Punkt die Entfernung zum Punkt P. Fügen Sie diese Entfernung in den Heap ein und löschen Sie das Maximum aus dem Heap, wenn die Größe des Heapspeichers größer ist als k.

Laufzeit: O(n log k)

6
Dukeling

Sie können KD tree http://en.wikipedia.org/wiki/K-d_tree verwenden, um Speicherplatz zu partitionieren. Wenn Sie den Punkt angeben, können Sie mit der binären Suche nach Nachbarn suchen Dieser Ansatz lässt sich leicht auf die Online-Version skalieren, wenn Sie zur Laufzeit Punkte/Abfragen nacheinander oder in Batches erhalten.

3
fury

Lösung 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;
    }
}

Lösung 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;
    }
}
1
hotpro
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;
}
}    
0
issam
// 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
0
Catriel

C # -Lösung mit LINQ

public int[][] KClosest(int[][] points, int K) {

    var orderedPoints = points.OrderBy(point => point[0]*point[0] + point[1]*point[1]);
    return orderedPoints.Take(K).ToArray();
}
0
havij