Find K nearest Points to Point P in 2-dimensional plane

后端 未结 9 1713
佛祖请我去吃肉
佛祖请我去吃肉 2021-01-31 04:27

Source: AMAZON INTERVIEW QUESTION

Given a point P and other N points in two dimensional space, find K points

相关标签:
9条回答
  • 2021-01-31 04:56

    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,

    0 讨论(0)
  • 2021-01-31 04:58

    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.

    0 讨论(0)
  • 2021-01-31 05:01

    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;
        }
    }
    
    0 讨论(0)
提交回复
热议问题