N Closest Points

Given a set of points, return the set of n closest points to the origin.

The Idea: The distance to any arbitrary point (x, y) from the origin can be defined with pythagoreans distances formula. d=x2x12+y2y12d = \sqrt{|x_2 - x_1|^2 + |y_2 - y_1|^2}. So all we do is sort on this basis.

Complexity: O(NlogN) time and O(1) space

Implementation 1:

using point = pair<int, int>;

double distance(const point &p)
{
    return sqrt(pow(p.first, 2) + pow(p.second, 2));
}

vector<point> closest_points( vector<point> &points,  int n)
{
    sort(points.begin(), points.end(), [](auto &left, auto &right) {
        return distance(left) < distance(right);
    });

    return vector<point>(points.begin(), points.begin() + n);
}

int main()
{
    vector<point> test = {
        {1,1}, {10,20}, {15, 8}, {1,0}, {2,3}, {5,6}
    };

    vector<point> cp = closest_points(test, 3);
    for (point p : cp) {
        cout << "(" << p.first << ", " << p.second << ")" << endl;
    }
}

Implementation 2:

Same complexity, subtle variation of work.

Implementation 3:

The Idea: The key point to realize is that we only need to maintain k elements, and these elements do not have to be sorted. If we maintain a heap of k elements, and simply continue popping the max distance (root) of the heap with the next smallest distance, we only do work proportional to the amount of elements maintained in the heap, which is k.

Complexity: O(N) + O(klog(k)) + O(k-n) + O(k). O(N) for finding the euclidean distances first, then O(klog(k)) for heapifying the first k elements, then O(k-n) checking the maintaining distances, and finally O(k) for pretty printing the actual coordinates from the tuples that were initially created.

Last updated

Was this helpful?