<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:
    vector<vector<int>> kClosest(vector<vector<int>>& points, int k) {
        if (k == points.size()) {
            return points;
        }

        list<float> dist, tmpdist;
        list<vector<int>> pts(points.begin(), points.end()), tmp;
        vector<vector<int>> res;
        for (auto& p : points) {
            float d = sqrt(p[0]*p[0] + p[1]*p[1]);
            dist.push_back(d);
        }

        int count = 0;
        int rem = k;
        float low = *min_element(dist.begin(), dist.end());
        float high = *max_element(dist.begin(), dist.end());
        size_t s = dist.size();

        while (true) {
            float mid = (low + high) / 2;
            auto it = pts.begin();
            auto dit = dist.begin();
            float new_low = high;
            for (size_t i = 0; i < s; i++) {
                if (*dit <= mid) {
                    tmp.push_back(*it);
                    tmpdist.push_back(*dit);
                    it = pts.erase(it);
                    dit = dist.erase(dit);
                    count++;
                } else {
                    if (*dit < new_low) {
                        new_low = *dit;
                    }
                    dit++;
                    it++;
                }
            }

            // Keep all the points
            if (count < rem) {
                low = new_low;
                // high stays the same in this case
                s = s - count;
                rem = rem - count;
                count = 0;
                res.insert(res.begin(), tmp.begin(), tmp.end());
                tmp.clear();
                tmpdist.clear();
            } else if (count > rem) {
                // Remove size - count elems from the front
                dist = tmpdist;
                pts = tmp;
                tmpdist.clear();
                tmp.clear();
                s = count;
                count = 0;
                low = *min_element(dist.begin(), dist.end());
                high = *max_element(dist.begin(), dist.end());
            } else if (count == rem) {
                // Remove size - k elems from the front
                res.insert(res.end(), tmp.begin(), tmp.end());
                break;
            }
            // If converged
            if (mid == (low + high)/2) {
                if (res.size()) {
                    res.resize(k);
                    return res;
                } else {
                    points.resize(k);
                    return points;
                }
            }
        }
        return res;
    }
};
118179