web-dev-qa-db-fra.com

Trouver K les points les plus proches du point P dans un plan à 2 dimensions

Source: Amazon INTERVIEW QUESTION

Étant donné un point P et d'autres N points dans un espace à deux dimensions, trouvez K points parmi les N points qui sont le plus proche de P.

Quel est le moyen le plus optimal de le faire?

Cette page Wiki ne fournit pas beaucoup d’aide pour la construction d’un algorithme. N'importe quelle idée/approche les gens.

18
Spandan

Solution 1 créez des tas de taille K et collectez des points par distance minimale O(NLogK) complexité.

Solution 2 : Prenez un tableau de taille N et triez-le par distance. Devrait être utilisé QuickSort (modification de Hoare) . Comme réponse, prenez d'abord K points . Cela est trop complexe, mais il est possible d'optimiser l'approximation de O (N) . Si le tri des sous-tableaux inutiles est omis. Lorsque vous scindez un tableau en deux sous-tableaux, vous ne devez utiliser que des tableaux où Kth index situé . Complexité sera: N + N/2 + N/4 + ... = O(N) .

Solution 3 : recherche le Kth élément dans le tableau de résultats et prend tout point inférieur à ce qui est fondé. Existe O(N) alghoritm, similaire à la recherche de la médiane.

Notes : mieux utiliser sqr de distance pour éviter des opérations de sqrt, il sera plus rapide si le point a des coordonnées entières.

En tant que réponse à l’entrevue, mieux utiliser les solutions 2 ou 3.

31
Толя

Pour une seule requête ...

Maintenir un tas de taille k.

Pour chaque point, calcule la distance jusqu'au point P. Insérez cette distance dans le tas et supprimez le maximum du tas si la taille du tas est supérieure à k.

Durée: O(n log k)

6
Dukeling

Vous pouvez utiliser KD tree http://en.wikipedia.org/wiki/K-d_tree pour partitionner l’espace et, étant donné le point, vous pourrez rechercher progressivement des voisins à l’aide de la recherche binaire ..__ Cette approche consiste à évoluer facilement jusqu'à la version en ligne lorsque vous recevez des points/requêtes au moment de l'exécution, un par un ou par lots.

3
fury

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;
    }
}
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