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

#include <iostream>

using namespace std;

class Solution {
public:
    vector<vector<int>> kClosest(vector<vector<int>>& points, int k) {
        vector<vector<int>> points_and_distances;

        for (std::vector<vector<int>>::iterator it = points.begin(); it != points.end(); it++) {
            int distance = ((*it)[0]*(*it)[0]) + ((*it)[1]*(*it)[1]);
            vector<int> point_and_distance{distance, (*it)[0], (*it)[1]};
            points_and_distances.push_back(point_and_distance);
        }


        for (int i = points_and_distances.size() - 1; i >= 0; i--) {
            sift_down(points_and_distances, i);
        }

        vector<vector<int>> ret_points;
        for (int i = 0; i < k; i++) { 
            vector<int> root = pop_root(points_and_distances);
            root[0] = root[1];
            root[1] = root[2];
            root.pop_back();
            ret_points.push_back(root);
        }

        return ret_points;
    }

    void sift_down(vector<vector<int>>& points_and_distances, int i) {
        int left_index = i*2 + 1;
        int right_index = i*2 + 2;

        //cout << "siftdown " << i << " " << points_and_distances.size() << endl;
        //cout << points_and_distances[i][0] << endl;

        if (left_index >= points_and_distances.size()) {
            return;
        }

        //cout << points_and_distances[left_index][0] << endl;
        if (right_index >= points_and_distances.size()) {

            if (points_and_distances[i][0] > points_and_distances[left_index][0]) {
                vector<int> temp = points_and_distances[i];
                points_and_distances[i] = points_and_distances[left_index];
                points_and_distances[left_index] = temp;
                sift_down(points_and_distances, left_index);
            }
        } else {
            //cout << points_and_distances[right_index][0] << endl;
            int smallest_child_index;
            if (points_and_distances[left_index][0] < points_and_distances[right_index][0]) {
                smallest_child_index = left_index;
            } else {
                smallest_child_index = right_index;
            }

            if (points_and_distances[i][0] > points_and_distances[smallest_child_index][0]) {
                vector<int> temp = points_and_distances[i];
                points_and_distances[i] = points_and_distances[smallest_child_index];
                points_and_distances[smallest_child_index] = temp;
                sift_down(points_and_distances, smallest_child_index);
            }
        }
    }

    vector<int> pop_root(vector<vector<int>>& points_and_distances) {
        vector<int> root = points_and_distances[0];
        points_and_distances[0] = points_and_distances[points_and_distances.size() - 1];
        points_and_distances.pop_back();
        sift_down(points_and_distances, 0);

        return root;
    }
};
123493