<p>Given an array of <code>points</code> where <code>points[i] = [x<sub>i</sub>, y<sub>i</sub>]</code> represents a point on the <strong>X-Y</strong> plane and an integer <code>k</code>, return the <code>k</code> closest points to the origin <code>(0, 0)</code>.</p>

<p>The distance between two points on the <strong>X-Y</strong> plane is the Euclidean distance (i.e., <code>&radic;(x<sub>1</sub> - x<sub>2</sub>)<sup>2</sup> + (y<sub>1</sub> - y<sub>2</sub>)<sup>2</sup></code>).</p>

<p>You may return the answer in <strong>any order</strong>. The answer is <strong>guaranteed</strong> to be <strong>unique</strong> (except for the order that it is in).</p>

<p>&nbsp;</p>
<p><strong class="example">Example 1:</strong></p>
<img alt="" src="https://assets.leetcode.com/uploads/2021/03/03/closestplane1.jpg" style="width: 400px; height: 400px;" />
<pre>
<strong>Input:</strong> points = [[1,3],[-2,2]], k = 1
<strong>Output:</strong> [[-2,2]]
<strong>Explanation:</strong>
The distance between (1, 3) and the origin is sqrt(10).
The distance between (-2, 2) and the origin is sqrt(8).
Since sqrt(8) &lt; sqrt(10), (-2, 2) is closer to the origin.
We only want the closest k = 1 points from the origin, so the answer is just [[-2,2]].
</pre>

<p><strong class="example">Example 2:</strong></p>

<pre>
<strong>Input:</strong> points = [[3,3],[5,-1],[-2,4]], k = 2
<strong>Output:</strong> [[3,3],[-2,4]]
<strong>Explanation:</strong> The answer [[-2,4],[3,3]] would also be accepted.
</pre>

<p>&nbsp;</p>
<p><strong>Constraints:</strong></p>

<ul>
	<li><code>1 &lt;= k &lt;= points.length &lt;= 10<sup>4</sup></code></li>
	<li><code>-10<sup>4</sup> &lt;= x<sub>i</sub>, y<sub>i</sub> &lt;= 10<sup>4</sup></code></li>
</ul>

class Solution {
public:
    static vector<vector<int>> kClosest(vector<vector<int>>& points, int k) {
        vector<pair<int, vector<int>>> ans;
        vector<vector<int>> res(k);
        ans.reserve(points.size());
        int low = 0;
        int high = (int)points.size() - 1;

        for (const auto& point: points) {
            int dist = point[0] * point[0] + point[1] * point[1];
            // pq.emplace(dist, point);
            // if (pq.size() > k) {
            //     pq.pop();
            // }

            ans.emplace_back(dist, point);
        }

        while (low < high) {
            swap(ans[getRandomNumber(low, high)], ans[low]);
            int part = partition(ans, low, high);

            if (part < k) {
                low = part + 1;
            } else {
                high = part;
            }
        }

        for (int i = 0; i < k; ++i) {
            res[i] = std::move(ans[i].second);
        }
        return res;

        // ans.reserve(k);

        // while (!pq.empty()) {
        //     auto &[_, point]  = pq.top();
        //     ans.emplace_back(point);
        //     pq.pop();
        // }

        // sort(points.begin(), points.end(), [&](const vector<int>& first, const vector<int>& second) {
        //     return (first[0] * first[0] + first[1] * first[1]) <
        //            (second[0] * second[0] + second[1] * second[1]);
        // });

        // return vector<vector<int>>(points.begin(), points.begin() + k);

        // return ans;
    }
private:
    static int getRandomNumber(int min, int max) {
        // Create a random device to seed the random number generator
        std::random_device rd;
        // Initialize Mersenne Twister pseudo-random number generator
        std::mt19937 gen(rd());
        // Create a uniform distribution in the range [min, max]
        std::uniform_int_distribution<> distr(min, max);

        // Generate and return a random number in the specified range
        return distr(gen);
    }
    static int partition(vector<pair<int, vector<int>>>& dists, int low, int high) {
        int pivot = dists[low].first;
        int i = low - 1;
        int j = high + 1;

        while (true) {
            do {
                ++i;
            } while (dists[i].first < pivot);
            do {
                --j;
            } while (dists[j].first > pivot);

            if (i >= j) {
                return j;
            }
            swap(dists[i], dists[j]);
        }
    }
};

const static auto _ = [](){
    cin.tie(nullptr);
    cout.tie(nullptr);
    ios_base::sync_with_stdio(false);
    return 0;
}();


70355