From 6a8339bdf6698a8b1533f171e6ecb482c1d0eeef Mon Sep 17 00:00:00 2001 From: rain84 Date: Mon, 1 Jul 2024 18:54:32 +0300 Subject: [PATCH 01/23] feat: add 2nd ts solution to lc problem: No.0973 --- .../0973.K Closest Points to Origin/README.md | 28 +++++++++++++++++++ .../README_EN.md | 28 +++++++++++++++++++ .../Solution2.ts | 13 +++++++++ 3 files changed, 69 insertions(+) create mode 100644 solution/0900-0999/0973.K Closest Points to Origin/Solution2.ts diff --git a/solution/0900-0999/0973.K Closest Points to Origin/README.md b/solution/0900-0999/0973.K Closest Points to Origin/README.md index 5350dbaa5b121..fb7850d47d25b 100644 --- a/solution/0900-0999/0973.K Closest Points to Origin/README.md +++ b/solution/0900-0999/0973.K Closest Points to Origin/README.md @@ -149,4 +149,32 @@ impl Solution { + + +### Solution 2. Priority queue + + + +#### TypeScript + +```ts +function kClosest(points: number[][], k: number): number[][] { + const minPQ = new MinPriorityQueue(); + + for (const [x, y] of points) { + const d = x ** 2 + y ** 2; + minPQ.enqueue([x, y], d); + } + + const res: number[][] = []; + while (k--) res.push(minPQ.dequeue().element); + + return res; +} +``` + + + + + diff --git a/solution/0900-0999/0973.K Closest Points to Origin/README_EN.md b/solution/0900-0999/0973.K Closest Points to Origin/README_EN.md index 21f0250eab7c1..7afdbbd0ded56 100644 --- a/solution/0900-0999/0973.K Closest Points to Origin/README_EN.md +++ b/solution/0900-0999/0973.K Closest Points to Origin/README_EN.md @@ -141,4 +141,32 @@ impl Solution { + + +### Solution 2. Priority queue + + + +#### TypeScript + +```ts +function kClosest(points: number[][], k: number): number[][] { + const minPQ = new MinPriorityQueue(); + + for (const [x, y] of points) { + const d = x ** 2 + y ** 2; + minPQ.enqueue([x, y], d); + } + + const res: number[][] = []; + while (k--) res.push(minPQ.dequeue().element); + + return res; +} +``` + + + + + diff --git a/solution/0900-0999/0973.K Closest Points to Origin/Solution2.ts b/solution/0900-0999/0973.K Closest Points to Origin/Solution2.ts new file mode 100644 index 0000000000000..27927150809b3 --- /dev/null +++ b/solution/0900-0999/0973.K Closest Points to Origin/Solution2.ts @@ -0,0 +1,13 @@ +function kClosest(points: number[][], k: number): number[][] { + const minPQ = new MinPriorityQueue(); + + for (const [x, y] of points) { + const d = x ** 2 + y ** 2; + minPQ.enqueue([x, y], d); + } + + const res: number[][] = []; + while (k--) res.push(minPQ.dequeue().element); + + return res; +} From 262c9f1b2c2f6c71f33cb0334316a5ccbac2569c Mon Sep 17 00:00:00 2001 From: rain84 Date: Mon, 1 Jul 2024 18:54:58 +0300 Subject: [PATCH 02/23] feat: add 3rd ts solution to lc problem: No.0973 --- .../0973.K Closest Points to Origin/README.md | 46 ++++++++++++++++++ .../README_EN.md | 48 +++++++++++++++++++ .../Solution3.ts | 31 ++++++++++++ 3 files changed, 125 insertions(+) create mode 100644 solution/0900-0999/0973.K Closest Points to Origin/Solution3.ts diff --git a/solution/0900-0999/0973.K Closest Points to Origin/README.md b/solution/0900-0999/0973.K Closest Points to Origin/README.md index fb7850d47d25b..0192edc478521 100644 --- a/solution/0900-0999/0973.K Closest Points to Origin/README.md +++ b/solution/0900-0999/0973.K Closest Points to Origin/README.md @@ -177,4 +177,50 @@ function kClosest(points: number[][], k: number): number[][] { + + +### Solution 3. Binary search + + + +#### TypeScript + +```ts +function kClosest(points: number[][], k: number): number[][] { + if (k === points.length) return points; + + const distance = points.map(([x, y]) => x ** 2 + y ** 2); + let indexes = points.map((_, i) => i); + let [l, r] = [0, Math.max(...distance)]; + const res: number[] = []; + + while (k) { + const mid = (l + r) >> 1; + + const closer: number[] = []; + const farther: number[] = []; + for (const i of indexes) { + if (distance[i] <= mid) closer.push(i); + else farther.push(i); + } + + if (closer.length > k) { + r = mid; + indexes = closer; + } else { + l = mid; + k -= closer.length; + res.push(...closer); + indexes = farther; + } + } + + return res.map(i => points[i]); +} +``` + + + + + diff --git a/solution/0900-0999/0973.K Closest Points to Origin/README_EN.md b/solution/0900-0999/0973.K Closest Points to Origin/README_EN.md index 7afdbbd0ded56..0998c265e0560 100644 --- a/solution/0900-0999/0973.K Closest Points to Origin/README_EN.md +++ b/solution/0900-0999/0973.K Closest Points to Origin/README_EN.md @@ -170,3 +170,51 @@ function kClosest(points: number[][], k: number): number[][] { + + + +### Solution 3. Binary search + + + +#### TypeScript + +```ts +function kClosest(points: number[][], k: number): number[][] { + if (k === points.length) return points; + + const distance = points.map(([x, y]) => x ** 2 + y ** 2); + let indexes = points.map((_, i) => i); + let [l, r] = [0, Math.max(...distance)]; + const res: number[] = []; + + while (k) { + const mid = (l + r) >> 1; + + const closer: number[] = []; + const farther: number[] = []; + for (const i of indexes) { + if (distance[i] <= mid) closer.push(i); + else farther.push(i); + } + + if (closer.length > k) { + r = mid; + indexes = closer; + } else { + l = mid; + k -= closer.length; + res.push(...closer); + indexes = farther; + } + } + + return res.map(i => points[i]); +} +``` + + + + + + diff --git a/solution/0900-0999/0973.K Closest Points to Origin/Solution3.ts b/solution/0900-0999/0973.K Closest Points to Origin/Solution3.ts new file mode 100644 index 0000000000000..16ff877f6ee51 --- /dev/null +++ b/solution/0900-0999/0973.K Closest Points to Origin/Solution3.ts @@ -0,0 +1,31 @@ +function kClosest(points: number[][], k: number): number[][] { + if (k === points.length) return points; + + const distance = points.map(([x, y]) => x ** 2 + y ** 2); + let indexes = points.map((_, i) => i); + let [l, r] = [0, Math.max(...distance)]; + const res: number[] = []; + + while (k) { + const mid = (l + r) >> 1; + + const closer: number[] = []; + const farther: number[] = []; + for (const i of indexes) { + if (distance[i] <= mid) closer.push(i); + else farther.push(i); + } + + if (closer.length > k) { + r = mid; + indexes = closer; + } else { + l = mid; + k -= closer.length; + res.push(...closer); + indexes = farther; + } + } + + return res.map(i => points[i]); +} From e5fa4d2f20d0e4c49b5b584dad7fbc5185624196 Mon Sep 17 00:00:00 2001 From: Libin YANG Date: Tue, 2 Jul 2024 19:30:12 +0800 Subject: [PATCH 03/23] Update README.md --- .../0973.K Closest Points to Origin/README.md | 319 +++++++++++++++--- 1 file changed, 270 insertions(+), 49 deletions(-) diff --git a/solution/0900-0999/0973.K Closest Points to Origin/README.md b/solution/0900-0999/0973.K Closest Points to Origin/README.md index 0192edc478521..a9c88c3d89b72 100644 --- a/solution/0900-0999/0973.K Closest Points to Origin/README.md +++ b/solution/0900-0999/0973.K Closest Points to Origin/README.md @@ -71,7 +71,7 @@ tags: 我们将所有点按照与原点的距离从小到大排序,然后取前 $k$ 个点即可。 -时间复杂度 $O(n \times \log n)$,空间复杂度 $O(\log n)$。其中 $n$ 为数组 `points` 的长度。 +时间复杂度 $O(n \times \log n)$,空间复杂度 $O(\log n)$。其中 $n$ 为数组 $\text{points}$ 的长度。 @@ -80,7 +80,7 @@ tags: ```python class Solution: def kClosest(self, points: List[List[int]], k: int) -> List[List[int]]: - points.sort(key=lambda p: p[0] * p[0] + p[1] * p[1]) + points.sort(key=lambda p: hypot(p[0], p[1])) return points[:k] ``` @@ -89,11 +89,7 @@ class Solution: ```java class Solution { public int[][] kClosest(int[][] points, int k) { - Arrays.sort(points, (a, b) -> { - int d1 = a[0] * a[0] + a[1] * a[1]; - int d2 = b[0] * b[0] + b[1] * b[1]; - return d1 - d2; - }); + Arrays.sort(points, (p1, p2) -> Math.hypot(p1[0], p1[1]) - Math.hypot(p2[0], p2[1]) > 0 ? 1 : -1); return Arrays.copyOfRange(points, 0, k); } } @@ -105,8 +101,8 @@ class Solution { class Solution { public: vector> kClosest(vector>& points, int k) { - sort(points.begin(), points.end(), [](const vector& a, const vector& b) { - return a[0] * a[0] + a[1] * a[1] < b[0] * b[0] + b[1] * b[1]; + sort(points.begin(), points.end(), [](const vector& p1, const vector& p2) { + return hypot(p1[0], p1[1]) < hypot(p2[0], p2[1]); }); return vector>(points.begin(), points.begin() + k); } @@ -118,8 +114,7 @@ public: ```go func kClosest(points [][]int, k int) [][]int { sort.Slice(points, func(i, j int) bool { - a, b := points[i], points[j] - return a[0]*a[0]+a[1]*a[1] < b[0]*b[0]+b[1]*b[1] + return math.Hypot(float64(points[i][0]), float64(points[i][1])) < math.Hypot(float64(points[j][0]), float64(points[j][1])) }) return points[:k] } @@ -129,7 +124,8 @@ func kClosest(points [][]int, k int) [][]int { ```ts function kClosest(points: number[][], k: number): number[][] { - return points.sort((a, b) => a[0] ** 2 + a[1] ** 2 - (b[0] ** 2 + b[1] ** 2)).slice(0, k); + points.sort((a, b) => Math.hypot(a[0], a[1]) - Math.hypot(b[0], b[1])); + return points.slice(0, k); } ``` @@ -138,9 +134,12 @@ function kClosest(points: number[][], k: number): number[][] { ```rust impl Solution { pub fn k_closest(mut points: Vec>, k: i32) -> Vec> { - points - .sort_unstable_by(|a, b| (a[0].pow(2) + a[1].pow(2)).cmp(&(b[0].pow(2) + b[1].pow(2)))); - points[0..k as usize].to_vec() + points.sort_by(|a, b| { + let dist_a = f64::hypot(a[0] as f64, a[1] as f64); + let dist_b = f64::hypot(b[0] as f64, b[1] as f64); + dist_a.partial_cmp(&dist_b).unwrap() + }); + points.into_iter().take(k as usize).collect() } } ``` @@ -151,25 +150,123 @@ impl Solution { -### Solution 2. Priority queue +### 方法二:优先队列(大根堆) + +我们可以使用一个优先队列(大根堆)来维护距离原点最近的 $k$ 个点。 + +时间复杂度 $O(n \times \log k)$,空间复杂度 $O(k)$。其中 $n$ 为数组 $\text{points}$ 的长度。 +#### Python3 + +```python +class Solution: + def kClosest(self, points: List[List[int]], k: int) -> List[List[int]]: + max_q = [] + for i, (x, y) in enumerate(points): + dist = math.hypot(x, y) + heappush(max_q, (-dist, i)) + if len(max_q) > k: + heappop(max_q) + return [points[i] for _, i in max_q] +``` + +#### Java + +```java +class Solution { + public int[][] kClosest(int[][] points, int k) { + PriorityQueue maxQ = new PriorityQueue<>((a, b) -> b[0] - a[0]); + for (int i = 0; i < points.length; ++i) { + int x = points[i][0], y = points[i][1]; + maxQ.offer(new int[] {x * x + y * y, i}); + if (maxQ.size() > k) { + maxQ.poll(); + } + } + int[][] ans = new int[k][2]; + for (int i = 0; i < k; ++i) { + ans[i] = points[maxQ.poll()[1]]; + } + return ans; + } +} +``` + +#### C++ + +```cpp +class Solution { +public: + vector> kClosest(vector>& points, int k) { + priority_queue> pq; + for (int i = 0, n = points.size(); i < n; ++i) { + double dist = hypot(points[i][0], points[i][1]); + pq.push({dist, i}); + if (pq.size() > k) { + pq.pop(); + } + } + vector> ans; + while (!pq.empty()) { + ans.push_back(points[pq.top().second]); + pq.pop(); + } + return ans; + } +}; +``` + +#### Go + +```go +func kClosest(points [][]int, k int) [][]int { + maxQ := hp{} + for i, p := range points { + dist := math.Hypot(float64(p[0]), float64(p[1])) + heap.Push(&maxQ, pair{dist, i}) + if len(maxQ) > k { + heap.Pop(&maxQ) + } + } + ans := make([][]int, k) + for i, p := range maxQ { + ans[i] = points[p.i] + } + return ans +} + +type pair struct { + dist float64 + i int +} + +type hp []pair + +func (h hp) Len() int { return len(h) } +func (h hp) Less(i, j int) bool { + a, b := h[i], h[j] + return a.dist > b.dist +} +func (h hp) Swap(i, j int) { h[i], h[j] = h[j], h[i] } +func (h *hp) Push(v any) { *h = append(*h, v.(pair)) } +func (h *hp) Pop() any { a := *h; v := a[len(a)-1]; *h = a[:len(a)-1]; return v } +``` + #### TypeScript ```ts function kClosest(points: number[][], k: number): number[][] { - const minPQ = new MinPriorityQueue(); - + const maxQ = new MaxPriorityQueue(); for (const [x, y] of points) { - const d = x ** 2 + y ** 2; - minPQ.enqueue([x, y], d); + const dist = x * x + y * y; + maxQ.enqueue([x, y], dist); + if (maxQ.size() > k) { + maxQ.dequeue(); + } } - - const res: number[][] = []; - while (k--) res.push(minPQ.dequeue().element); - - return res; + return maxQ.toArray().map(item => item.element); } ``` @@ -179,43 +276,167 @@ function kClosest(points: number[][], k: number): number[][] { -### Solution 3. Binary search +### 方法三:二分查找 + +我们注意到,随着距离的增大,点的数量是递增的。这存在一个临界值,使得在这个值之前的点的数量小于等于 $k$,而在这个值之后的点的数量大于 $k$。 + +因此,我们可以使用二分查找,枚举距离。每一次二分查找,我们统计出距离小于等于当前距离的点的数量,如果数量大于等于 $k$,则说明临界值在左侧,我们令右边界等于当前距离;否则,临界值在右侧,我们令左边界等于当前距禽加一。 + +二分查找结束后,我们只需要返回距离小于等于左边界的点即可。 + +时间复杂度 $O(n \times \log M)$,空间复杂度 $O(n)$。其中 $n$ 为数组 $\text{points}$ 的长度,而 $M$ 为距离的最大值。 -#### TypeScript +#### Python3 -```ts -function kClosest(points: number[][], k: number): number[][] { - if (k === points.length) return points; +```python +class Solution: + def kClosest(self, points: List[List[int]], k: int) -> List[List[int]]: + dist = [x * x + y * y for x, y in points] + l, r = 0, max(dist) + while l < r: + mid = (l + r) >> 1 + cnt = sum(d <= mid for d in dist) + if cnt >= k: + r = mid + else: + l = mid + 1 + return [points[i] for i, d in enumerate(dist) if d <= l] +``` - const distance = points.map(([x, y]) => x ** 2 + y ** 2); - let indexes = points.map((_, i) => i); - let [l, r] = [0, Math.max(...distance)]; - const res: number[] = []; +#### Java - while (k) { - const mid = (l + r) >> 1; +```java +class Solution { + public int[][] kClosest(int[][] points, int k) { + int n = points.length; + int[] dist = new int[n]; + int r = 0; + for (int i = 0; i < n; ++i) { + int x = points[i][0], y = points[i][1]; + dist[i] = x * x + y * y; + r = Math.max(r, dist[i]); + } + int l = 0; + while (l < r) { + int mid = (l + r) >> 1; + int cnt = 0; + for (int d : dist) { + if (d <= mid) { + ++cnt; + } + } + if (cnt >= k) { + r = mid; + } else { + l = mid + 1; + } + } + int[][] ans = new int[k][0]; + for (int i = 0, j = 0; i < n; ++i) { + if (dist[i] <= l) { + ans[j++] = points[i]; + } + } + return ans; + } +} +``` - const closer: number[] = []; - const farther: number[] = []; - for (const i of indexes) { - if (distance[i] <= mid) closer.push(i); - else farther.push(i); +#### C++ + +```cpp +class Solution { +public: + vector> kClosest(vector>& points, int k) { + int n = points.size(); + int dist[n]; + int r = 0; + for (int i = 0; i < n; ++i) { + int x = points[i][0], y = points[i][1]; + dist[i] = x * x + y * y; + r = max(r, dist[i]); } + int l = 0; + while (l < r) { + int mid = (l + r) >> 1; + int cnt = 0; + for (int d : dist) { + cnt += d <= mid; + } + if (cnt >= k) { + r = mid; + } else { + l = mid + 1; + } + } + vector> ans; + for (int i = 0; i < n; ++i) { + if (dist[i] <= l) { + ans.emplace_back(points[i]); + } + } + return ans; + } +}; +``` + +#### Go + +```go +func kClosest(points [][]int, k int) (ans [][]int) { + n := len(points) + dist := make([]int, n) + l, r := 0, 0 + for i, p := range points { + dist[i] = p[0]*p[0] + p[1]*p[1] + r = max(r, dist[i]) + } + for l < r { + mid := (l + r) >> 1 + cnt := 0 + for _, d := range dist { + if d <= mid { + cnt++ + } + } + if cnt >= k { + r = mid + } else { + l = mid + 1 + } + } + for i, p := range points { + if dist[i] <= l { + ans = append(ans, p) + } + } + return +} +``` + +#### TypeScript - if (closer.length > k) { +```ts +function kClosest(points: number[][], k: number): number[][] { + const dist = points.map(([x, y]) => x * x + y * y); + let [l, r] = [0, Math.max(...dist)]; + while (l < r) { + const mid = (l + r) >> 1; + let cnt = 0; + for (const d of dist) { + if (d <= mid) { + ++cnt; + } + } + if (cnt >= k) { r = mid; - indexes = closer; } else { - l = mid; - k -= closer.length; - res.push(...closer); - indexes = farther; + l = mid + 1; } } - - return res.map(i => points[i]); + return points.filter((_, i) => dist[i] <= l); } ``` From 845cf47ec7bfe785f00594fad47feb8181b8af04 Mon Sep 17 00:00:00 2001 From: Libin YANG Date: Tue, 2 Jul 2024 19:30:27 +0800 Subject: [PATCH 04/23] Update README_EN.md --- .../README_EN.md | 325 +++++++++++++++--- 1 file changed, 274 insertions(+), 51 deletions(-) diff --git a/solution/0900-0999/0973.K Closest Points to Origin/README_EN.md b/solution/0900-0999/0973.K Closest Points to Origin/README_EN.md index 0998c265e0560..a7257ca6ce307 100644 --- a/solution/0900-0999/0973.K Closest Points to Origin/README_EN.md +++ b/solution/0900-0999/0973.K Closest Points to Origin/README_EN.md @@ -63,7 +63,11 @@ We only want the closest k = 1 points from the origin, so the answer is just [[- -### Solution 1 +### Solution 1: Custom Sorting + +We sort all points by their distance from the origin in ascending order, and then take the first $k$ points. + +The time complexity is $O(n \log n)$, and the space complexity is $O(\log n)$. Here, $n$ is the length of the array $\text{points}$. @@ -72,7 +76,7 @@ We only want the closest k = 1 points from the origin, so the answer is just [[- ```python class Solution: def kClosest(self, points: List[List[int]], k: int) -> List[List[int]]: - points.sort(key=lambda p: p[0] * p[0] + p[1] * p[1]) + points.sort(key=lambda p: hypot(p[0], p[1])) return points[:k] ``` @@ -81,11 +85,7 @@ class Solution: ```java class Solution { public int[][] kClosest(int[][] points, int k) { - Arrays.sort(points, (a, b) -> { - int d1 = a[0] * a[0] + a[1] * a[1]; - int d2 = b[0] * b[0] + b[1] * b[1]; - return d1 - d2; - }); + Arrays.sort(points, (p1, p2) -> Math.hypot(p1[0], p1[1]) - Math.hypot(p2[0], p2[1]) > 0 ? 1 : -1); return Arrays.copyOfRange(points, 0, k); } } @@ -97,8 +97,8 @@ class Solution { class Solution { public: vector> kClosest(vector>& points, int k) { - sort(points.begin(), points.end(), [](const vector& a, const vector& b) { - return a[0] * a[0] + a[1] * a[1] < b[0] * b[0] + b[1] * b[1]; + sort(points.begin(), points.end(), [](const vector& p1, const vector& p2) { + return hypot(p1[0], p1[1]) < hypot(p2[0], p2[1]); }); return vector>(points.begin(), points.begin() + k); } @@ -110,8 +110,7 @@ public: ```go func kClosest(points [][]int, k int) [][]int { sort.Slice(points, func(i, j int) bool { - a, b := points[i], points[j] - return a[0]*a[0]+a[1]*a[1] < b[0]*b[0]+b[1]*b[1] + return math.Hypot(float64(points[i][0]), float64(points[i][1])) < math.Hypot(float64(points[j][0]), float64(points[j][1])) }) return points[:k] } @@ -121,7 +120,8 @@ func kClosest(points [][]int, k int) [][]int { ```ts function kClosest(points: number[][], k: number): number[][] { - return points.sort((a, b) => a[0] ** 2 + a[1] ** 2 - (b[0] ** 2 + b[1] ** 2)).slice(0, k); + points.sort((a, b) => Math.hypot(a[0], a[1]) - Math.hypot(b[0], b[1])); + return points.slice(0, k); } ``` @@ -130,9 +130,12 @@ function kClosest(points: number[][], k: number): number[][] { ```rust impl Solution { pub fn k_closest(mut points: Vec>, k: i32) -> Vec> { - points - .sort_unstable_by(|a, b| (a[0].pow(2) + a[1].pow(2)).cmp(&(b[0].pow(2) + b[1].pow(2)))); - points[0..k as usize].to_vec() + points.sort_by(|a, b| { + let dist_a = f64::hypot(a[0] as f64, a[1] as f64); + let dist_b = f64::hypot(b[0] as f64, b[1] as f64); + dist_a.partial_cmp(&dist_b).unwrap() + }); + points.into_iter().take(k as usize).collect() } } ``` @@ -143,25 +146,123 @@ impl Solution { -### Solution 2. Priority queue +### Solution 2: Priority Queue (Max Heap) + +We can use a priority queue (max heap) to maintain the $k$ closest points to the origin. + +The time complexity is $O(n \times \log k)$, and the space complexity is $O(k)$. Here, $n$ is the length of the array $\text{points}$. +#### Python3 + +```python +class Solution: + def kClosest(self, points: List[List[int]], k: int) -> List[List[int]]: + max_q = [] + for i, (x, y) in enumerate(points): + dist = math.hypot(x, y) + heappush(max_q, (-dist, i)) + if len(max_q) > k: + heappop(max_q) + return [points[i] for _, i in max_q] +``` + +#### Java + +```java +class Solution { + public int[][] kClosest(int[][] points, int k) { + PriorityQueue maxQ = new PriorityQueue<>((a, b) -> b[0] - a[0]); + for (int i = 0; i < points.length; ++i) { + int x = points[i][0], y = points[i][1]; + maxQ.offer(new int[] {x * x + y * y, i}); + if (maxQ.size() > k) { + maxQ.poll(); + } + } + int[][] ans = new int[k][2]; + for (int i = 0; i < k; ++i) { + ans[i] = points[maxQ.poll()[1]]; + } + return ans; + } +} +``` + +#### C++ + +```cpp +class Solution { +public: + vector> kClosest(vector>& points, int k) { + priority_queue> pq; + for (int i = 0, n = points.size(); i < n; ++i) { + double dist = hypot(points[i][0], points[i][1]); + pq.push({dist, i}); + if (pq.size() > k) { + pq.pop(); + } + } + vector> ans; + while (!pq.empty()) { + ans.push_back(points[pq.top().second]); + pq.pop(); + } + return ans; + } +}; +``` + +#### Go + +```go +func kClosest(points [][]int, k int) [][]int { + maxQ := hp{} + for i, p := range points { + dist := math.Hypot(float64(p[0]), float64(p[1])) + heap.Push(&maxQ, pair{dist, i}) + if len(maxQ) > k { + heap.Pop(&maxQ) + } + } + ans := make([][]int, k) + for i, p := range maxQ { + ans[i] = points[p.i] + } + return ans +} + +type pair struct { + dist float64 + i int +} + +type hp []pair + +func (h hp) Len() int { return len(h) } +func (h hp) Less(i, j int) bool { + a, b := h[i], h[j] + return a.dist > b.dist +} +func (h hp) Swap(i, j int) { h[i], h[j] = h[j], h[i] } +func (h *hp) Push(v any) { *h = append(*h, v.(pair)) } +func (h *hp) Pop() any { a := *h; v := a[len(a)-1]; *h = a[:len(a)-1]; return v } +``` + #### TypeScript ```ts function kClosest(points: number[][], k: number): number[][] { - const minPQ = new MinPriorityQueue(); - + const maxQ = new MaxPriorityQueue(); for (const [x, y] of points) { - const d = x ** 2 + y ** 2; - minPQ.enqueue([x, y], d); + const dist = x * x + y * y; + maxQ.enqueue([x, y], dist); + if (maxQ.size() > k) { + maxQ.dequeue(); + } } - - const res: number[][] = []; - while (k--) res.push(minPQ.dequeue().element); - - return res; + return maxQ.toArray().map(item => item.element); } ``` @@ -169,47 +270,169 @@ function kClosest(points: number[][], k: number): number[][] { - - -### Solution 3. Binary search +### Solution 3: Binary Search + +We notice that as the distance increases, the number of points increases as well. There exists a critical value such that the number of points before this value is less than or equal to $k$, and the number of points after this value is greater than $k$. + +Therefore, we can use binary search to enumerate the distance. In each binary search iteration, we count the number of points whose distance is less than or equal to the current distance. If the count is greater than or equal to $k$, it indicates that the critical value is on the left side, so we set the right boundary equal to the current distance; otherwise, the critical value is on the right side, so we set the left boundary equal to the current distance plus one. + +After the binary search is finished, we just need to return the points whose distance is less than or equal to the left boundary. + +The time complexity is $O(n \times \log M)$, and the space complexity is $O(n)$. Here, $n$ is the length of the array $\text{points}$, and $M$ is the maximum value of the distance. -#### TypeScript +#### Python3 -```ts -function kClosest(points: number[][], k: number): number[][] { - if (k === points.length) return points; +```python +class Solution: + def kClosest(self, points: List[List[int]], k: int) -> List[List[int]]: + dist = [x * x + y * y for x, y in points] + l, r = 0, max(dist) + while l < r: + mid = (l + r) >> 1 + cnt = sum(d <= mid for d in dist) + if cnt >= k: + r = mid + else: + l = mid + 1 + return [points[i] for i, d in enumerate(dist) if d <= l] +``` - const distance = points.map(([x, y]) => x ** 2 + y ** 2); - let indexes = points.map((_, i) => i); - let [l, r] = [0, Math.max(...distance)]; - const res: number[] = []; +#### Java - while (k) { - const mid = (l + r) >> 1; +```java +class Solution { + public int[][] kClosest(int[][] points, int k) { + int n = points.length; + int[] dist = new int[n]; + int r = 0; + for (int i = 0; i < n; ++i) { + int x = points[i][0], y = points[i][1]; + dist[i] = x * x + y * y; + r = Math.max(r, dist[i]); + } + int l = 0; + while (l < r) { + int mid = (l + r) >> 1; + int cnt = 0; + for (int d : dist) { + if (d <= mid) { + ++cnt; + } + } + if (cnt >= k) { + r = mid; + } else { + l = mid + 1; + } + } + int[][] ans = new int[k][0]; + for (int i = 0, j = 0; i < n; ++i) { + if (dist[i] <= l) { + ans[j++] = points[i]; + } + } + return ans; + } +} +``` + +#### C++ - const closer: number[] = []; - const farther: number[] = []; - for (const i of indexes) { - if (distance[i] <= mid) closer.push(i); - else farther.push(i); +```cpp +class Solution { +public: + vector> kClosest(vector>& points, int k) { + int n = points.size(); + int dist[n]; + int r = 0; + for (int i = 0; i < n; ++i) { + int x = points[i][0], y = points[i][1]; + dist[i] = x * x + y * y; + r = max(r, dist[i]); } + int l = 0; + while (l < r) { + int mid = (l + r) >> 1; + int cnt = 0; + for (int d : dist) { + cnt += d <= mid; + } + if (cnt >= k) { + r = mid; + } else { + l = mid + 1; + } + } + vector> ans; + for (int i = 0; i < n; ++i) { + if (dist[i] <= l) { + ans.emplace_back(points[i]); + } + } + return ans; + } +}; +``` - if (closer.length > k) { +#### Go + +```go +func kClosest(points [][]int, k int) (ans [][]int) { + n := len(points) + dist := make([]int, n) + l, r := 0, 0 + for i, p := range points { + dist[i] = p[0]*p[0] + p[1]*p[1] + r = max(r, dist[i]) + } + for l < r { + mid := (l + r) >> 1 + cnt := 0 + for _, d := range dist { + if d <= mid { + cnt++ + } + } + if cnt >= k { + r = mid + } else { + l = mid + 1 + } + } + for i, p := range points { + if dist[i] <= l { + ans = append(ans, p) + } + } + return +} +``` + +#### TypeScript + +```ts +function kClosest(points: number[][], k: number): number[][] { + const dist = points.map(([x, y]) => x * x + y * y); + let [l, r] = [0, Math.max(...dist)]; + while (l < r) { + const mid = (l + r) >> 1; + let cnt = 0; + for (const d of dist) { + if (d <= mid) { + ++cnt; + } + } + if (cnt >= k) { r = mid; - indexes = closer; } else { - l = mid; - k -= closer.length; - res.push(...closer); - indexes = farther; + l = mid + 1; } } - - return res.map(i => points[i]); + return points.filter((_, i) => dist[i] <= l); } ``` From 8b23833798edceac2c6e0aef4fab9247b89561a1 Mon Sep 17 00:00:00 2001 From: Libin YANG Date: Tue, 2 Jul 2024 20:03:50 +0800 Subject: [PATCH 05/23] Update Solution.py --- solution/0900-0999/0973.K Closest Points to Origin/Solution.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/solution/0900-0999/0973.K Closest Points to Origin/Solution.py b/solution/0900-0999/0973.K Closest Points to Origin/Solution.py index 5213bb7d71664..6295e8ff64941 100644 --- a/solution/0900-0999/0973.K Closest Points to Origin/Solution.py +++ b/solution/0900-0999/0973.K Closest Points to Origin/Solution.py @@ -1,4 +1,4 @@ class Solution: def kClosest(self, points: List[List[int]], k: int) -> List[List[int]]: - points.sort(key=lambda p: p[0] * p[0] + p[1] * p[1]) + points.sort(key=lambda p: hypot(p[0], p[1])) return points[:k] From 9395fb620ffdcde857570ad475a6e0490a767d22 Mon Sep 17 00:00:00 2001 From: Libin YANG Date: Tue, 2 Jul 2024 20:03:59 +0800 Subject: [PATCH 06/23] Update Solution.java --- .../0973.K Closest Points to Origin/Solution.java | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/solution/0900-0999/0973.K Closest Points to Origin/Solution.java b/solution/0900-0999/0973.K Closest Points to Origin/Solution.java index 4a6b291695941..e84831659999b 100644 --- a/solution/0900-0999/0973.K Closest Points to Origin/Solution.java +++ b/solution/0900-0999/0973.K Closest Points to Origin/Solution.java @@ -1,10 +1,6 @@ class Solution { public int[][] kClosest(int[][] points, int k) { - Arrays.sort(points, (a, b) -> { - int d1 = a[0] * a[0] + a[1] * a[1]; - int d2 = b[0] * b[0] + b[1] * b[1]; - return d1 - d2; - }); + Arrays.sort(points, (p1, p2) -> Math.hypot(p1[0], p1[1]) - Math.hypot(p2[0], p2[1]) > 0 ? 1 : -1); return Arrays.copyOfRange(points, 0, k); } -} \ No newline at end of file +} From b40e92a3a9c1271d9b9149298870a86d9e1aa349 Mon Sep 17 00:00:00 2001 From: Libin YANG Date: Tue, 2 Jul 2024 20:04:11 +0800 Subject: [PATCH 07/23] Update Solution.cpp --- .../0900-0999/0973.K Closest Points to Origin/Solution.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/solution/0900-0999/0973.K Closest Points to Origin/Solution.cpp b/solution/0900-0999/0973.K Closest Points to Origin/Solution.cpp index c58427ddd8fee..c30a05538fac1 100644 --- a/solution/0900-0999/0973.K Closest Points to Origin/Solution.cpp +++ b/solution/0900-0999/0973.K Closest Points to Origin/Solution.cpp @@ -1,9 +1,9 @@ class Solution { public: vector> kClosest(vector>& points, int k) { - sort(points.begin(), points.end(), [](const vector& a, const vector& b) { - return a[0] * a[0] + a[1] * a[1] < b[0] * b[0] + b[1] * b[1]; + sort(points.begin(), points.end(), [](const vector& p1, const vector& p2) { + return hypot(p1[0], p1[1]) < hypot(p2[0], p2[1]); }); return vector>(points.begin(), points.begin() + k); } -}; \ No newline at end of file +}; From 0c5292148023782703739bf81c09efc7b343048c Mon Sep 17 00:00:00 2001 From: Libin YANG Date: Tue, 2 Jul 2024 20:04:20 +0800 Subject: [PATCH 08/23] Update Solution.go --- .../0900-0999/0973.K Closest Points to Origin/Solution.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/solution/0900-0999/0973.K Closest Points to Origin/Solution.go b/solution/0900-0999/0973.K Closest Points to Origin/Solution.go index 381165720b9b7..e3bc3238ac104 100644 --- a/solution/0900-0999/0973.K Closest Points to Origin/Solution.go +++ b/solution/0900-0999/0973.K Closest Points to Origin/Solution.go @@ -1,7 +1,6 @@ func kClosest(points [][]int, k int) [][]int { sort.Slice(points, func(i, j int) bool { - a, b := points[i], points[j] - return a[0]*a[0]+a[1]*a[1] < b[0]*b[0]+b[1]*b[1] + return math.Hypot(float64(points[i][0]), float64(points[i][1])) < math.Hypot(float64(points[j][0]), float64(points[j][1])) }) return points[:k] -} \ No newline at end of file +} From 15168860404b7df70b86a936809a038df7c9b0b6 Mon Sep 17 00:00:00 2001 From: Libin YANG Date: Tue, 2 Jul 2024 20:04:37 +0800 Subject: [PATCH 09/23] Update Solution.ts --- solution/0900-0999/0973.K Closest Points to Origin/Solution.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/solution/0900-0999/0973.K Closest Points to Origin/Solution.ts b/solution/0900-0999/0973.K Closest Points to Origin/Solution.ts index 37cc3ccf2a10a..b287aa6e0cce3 100644 --- a/solution/0900-0999/0973.K Closest Points to Origin/Solution.ts +++ b/solution/0900-0999/0973.K Closest Points to Origin/Solution.ts @@ -1,3 +1,4 @@ function kClosest(points: number[][], k: number): number[][] { - return points.sort((a, b) => a[0] ** 2 + a[1] ** 2 - (b[0] ** 2 + b[1] ** 2)).slice(0, k); + points.sort((a, b) => Math.hypot(a[0], a[1]) - Math.hypot(b[0], b[1])); + return points.slice(0, k); } From 320f26d32101d3f282df7d4a1170e2cbaeaee20d Mon Sep 17 00:00:00 2001 From: Libin YANG Date: Tue, 2 Jul 2024 20:04:50 +0800 Subject: [PATCH 10/23] Update Solution2.ts --- .../0973.K Closest Points to Origin/Solution2.ts | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/solution/0900-0999/0973.K Closest Points to Origin/Solution2.ts b/solution/0900-0999/0973.K Closest Points to Origin/Solution2.ts index 27927150809b3..afeb1c9d648f6 100644 --- a/solution/0900-0999/0973.K Closest Points to Origin/Solution2.ts +++ b/solution/0900-0999/0973.K Closest Points to Origin/Solution2.ts @@ -1,13 +1,11 @@ function kClosest(points: number[][], k: number): number[][] { - const minPQ = new MinPriorityQueue(); - + const maxQ = new MaxPriorityQueue(); for (const [x, y] of points) { - const d = x ** 2 + y ** 2; - minPQ.enqueue([x, y], d); + const dist = x * x + y * y; + maxQ.enqueue([x, y], dist); + if (maxQ.size() > k) { + maxQ.dequeue(); + } } - - const res: number[][] = []; - while (k--) res.push(minPQ.dequeue().element); - - return res; + return maxQ.toArray().map(item => item.element); } From 418399485ad8e6a89db2220edd4a66a4d23976b8 Mon Sep 17 00:00:00 2001 From: Libin YANG Date: Tue, 2 Jul 2024 20:04:59 +0800 Subject: [PATCH 11/23] Update Solution3.ts --- .../Solution3.ts | 34 ++++++------------- 1 file changed, 11 insertions(+), 23 deletions(-) diff --git a/solution/0900-0999/0973.K Closest Points to Origin/Solution3.ts b/solution/0900-0999/0973.K Closest Points to Origin/Solution3.ts index 16ff877f6ee51..47e00c9ffadbf 100644 --- a/solution/0900-0999/0973.K Closest Points to Origin/Solution3.ts +++ b/solution/0900-0999/0973.K Closest Points to Origin/Solution3.ts @@ -1,31 +1,19 @@ function kClosest(points: number[][], k: number): number[][] { - if (k === points.length) return points; - - const distance = points.map(([x, y]) => x ** 2 + y ** 2); - let indexes = points.map((_, i) => i); - let [l, r] = [0, Math.max(...distance)]; - const res: number[] = []; - - while (k) { + const dist = points.map(([x, y]) => x * x + y * y); + let [l, r] = [0, Math.max(...dist)]; + while (l < r) { const mid = (l + r) >> 1; - - const closer: number[] = []; - const farther: number[] = []; - for (const i of indexes) { - if (distance[i] <= mid) closer.push(i); - else farther.push(i); + let cnt = 0; + for (const d of dist) { + if (d <= mid) { + ++cnt; + } } - - if (closer.length > k) { + if (cnt >= k) { r = mid; - indexes = closer; } else { - l = mid; - k -= closer.length; - res.push(...closer); - indexes = farther; + l = mid + 1; } } - - return res.map(i => points[i]); + return points.filter((_, i) => dist[i] <= l); } From 1bae725eae87ee2e3d75b38f95e4b02d6afbd64b Mon Sep 17 00:00:00 2001 From: Libin YANG Date: Tue, 2 Jul 2024 20:05:11 +0800 Subject: [PATCH 12/23] Create Solution2.java --- .../Solution2.java | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 solution/0900-0999/0973.K Closest Points to Origin/Solution2.java diff --git a/solution/0900-0999/0973.K Closest Points to Origin/Solution2.java b/solution/0900-0999/0973.K Closest Points to Origin/Solution2.java new file mode 100644 index 0000000000000..4cbd4480fd52b --- /dev/null +++ b/solution/0900-0999/0973.K Closest Points to Origin/Solution2.java @@ -0,0 +1,17 @@ +class Solution { + public int[][] kClosest(int[][] points, int k) { + PriorityQueue maxQ = new PriorityQueue<>((a, b) -> b[0] - a[0]); + for (int i = 0; i < points.length; ++i) { + int x = points[i][0], y = points[i][1]; + maxQ.offer(new int[] {x * x + y * y, i}); + if (maxQ.size() > k) { + maxQ.poll(); + } + } + int[][] ans = new int[k][2]; + for (int i = 0; i < k; ++i) { + ans[i] = points[maxQ.poll()[1]]; + } + return ans; + } +} From c94329e28244a77beb357c5dbc21eb0d6afd9d62 Mon Sep 17 00:00:00 2001 From: Libin YANG Date: Tue, 2 Jul 2024 20:05:22 +0800 Subject: [PATCH 13/23] Create Solution2.cpp --- .../Solution2.cpp | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 solution/0900-0999/0973.K Closest Points to Origin/Solution2.cpp diff --git a/solution/0900-0999/0973.K Closest Points to Origin/Solution2.cpp b/solution/0900-0999/0973.K Closest Points to Origin/Solution2.cpp new file mode 100644 index 0000000000000..1afd54881db59 --- /dev/null +++ b/solution/0900-0999/0973.K Closest Points to Origin/Solution2.cpp @@ -0,0 +1,19 @@ +class Solution { +public: + vector> kClosest(vector>& points, int k) { + priority_queue> pq; + for (int i = 0, n = points.size(); i < n; ++i) { + double dist = hypot(points[i][0], points[i][1]); + pq.push({dist, i}); + if (pq.size() > k) { + pq.pop(); + } + } + vector> ans; + while (!pq.empty()) { + ans.push_back(points[pq.top().second]); + pq.pop(); + } + return ans; + } +}; From 59a39a8a3cfff0031ff2638846dc92fe2231c5e0 Mon Sep 17 00:00:00 2001 From: Libin YANG Date: Tue, 2 Jul 2024 20:05:41 +0800 Subject: [PATCH 14/23] Create Solution2.go --- .../Solution2.go | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 solution/0900-0999/0973.K Closest Points to Origin/Solution2.go diff --git a/solution/0900-0999/0973.K Closest Points to Origin/Solution2.go b/solution/0900-0999/0973.K Closest Points to Origin/Solution2.go new file mode 100644 index 0000000000000..cd1b7aac2f2db --- /dev/null +++ b/solution/0900-0999/0973.K Closest Points to Origin/Solution2.go @@ -0,0 +1,31 @@ +func kClosest(points [][]int, k int) [][]int { + maxQ := hp{} + for i, p := range points { + dist := math.Hypot(float64(p[0]), float64(p[1])) + heap.Push(&maxQ, pair{dist, i}) + if len(maxQ) > k { + heap.Pop(&maxQ) + } + } + ans := make([][]int, k) + for i, p := range maxQ { + ans[i] = points[p.i] + } + return ans +} + +type pair struct { + dist float64 + i int +} + +type hp []pair + +func (h hp) Len() int { return len(h) } +func (h hp) Less(i, j int) bool { + a, b := h[i], h[j] + return a.dist > b.dist +} +func (h hp) Swap(i, j int) { h[i], h[j] = h[j], h[i] } +func (h *hp) Push(v any) { *h = append(*h, v.(pair)) } +func (h *hp) Pop() any { a := *h; v := a[len(a)-1]; *h = a[:len(a)-1]; return v } From cc0526c4b165dd8082a0a8ce2872652258d137af Mon Sep 17 00:00:00 2001 From: Libin YANG Date: Tue, 2 Jul 2024 20:05:57 +0800 Subject: [PATCH 15/23] Create Solution3.java --- .../Solution3.java | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 solution/0900-0999/0973.K Closest Points to Origin/Solution3.java diff --git a/solution/0900-0999/0973.K Closest Points to Origin/Solution3.java b/solution/0900-0999/0973.K Closest Points to Origin/Solution3.java new file mode 100644 index 0000000000000..32b91730e299e --- /dev/null +++ b/solution/0900-0999/0973.K Closest Points to Origin/Solution3.java @@ -0,0 +1,34 @@ +class Solution { + public int[][] kClosest(int[][] points, int k) { + int n = points.length; + int[] dist = new int[n]; + int r = 0; + for (int i = 0; i < n; ++i) { + int x = points[i][0], y = points[i][1]; + dist[i] = x * x + y * y; + r = Math.max(r, dist[i]); + } + int l = 0; + while (l < r) { + int mid = (l + r) >> 1; + int cnt = 0; + for (int d : dist) { + if (d <= mid) { + ++cnt; + } + } + if (cnt >= k) { + r = mid; + } else { + l = mid + 1; + } + } + int[][] ans = new int[k][0]; + for (int i = 0, j = 0; i < n; ++i) { + if (dist[i] <= l) { + ans[j++] = points[i]; + } + } + return ans; + } +} From b00e38c8b69230db7ab94f2eee51c5d442a84dcc Mon Sep 17 00:00:00 2001 From: Libin YANG Date: Tue, 2 Jul 2024 20:06:09 +0800 Subject: [PATCH 16/23] Create Solution3.cpp --- .../Solution3.cpp | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 solution/0900-0999/0973.K Closest Points to Origin/Solution3.cpp diff --git a/solution/0900-0999/0973.K Closest Points to Origin/Solution3.cpp b/solution/0900-0999/0973.K Closest Points to Origin/Solution3.cpp new file mode 100644 index 0000000000000..af2dacde72826 --- /dev/null +++ b/solution/0900-0999/0973.K Closest Points to Origin/Solution3.cpp @@ -0,0 +1,33 @@ +class Solution { +public: + vector> kClosest(vector>& points, int k) { + int n = points.size(); + int dist[n]; + int r = 0; + for (int i = 0; i < n; ++i) { + int x = points[i][0], y = points[i][1]; + dist[i] = x * x + y * y; + r = max(r, dist[i]); + } + int l = 0; + while (l < r) { + int mid = (l + r) >> 1; + int cnt = 0; + for (int d : dist) { + cnt += d <= mid; + } + if (cnt >= k) { + r = mid; + } else { + l = mid + 1; + } + } + vector> ans; + for (int i = 0; i < n; ++i) { + if (dist[i] <= l) { + ans.emplace_back(points[i]); + } + } + return ans; + } +}; From cdbc09fb323e46c6660e86fc7989ae19a56d42c3 Mon Sep 17 00:00:00 2001 From: Libin YANG Date: Tue, 2 Jul 2024 20:06:20 +0800 Subject: [PATCH 17/23] Create Solution3.go --- .../Solution3.go | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 solution/0900-0999/0973.K Closest Points to Origin/Solution3.go diff --git a/solution/0900-0999/0973.K Closest Points to Origin/Solution3.go b/solution/0900-0999/0973.K Closest Points to Origin/Solution3.go new file mode 100644 index 0000000000000..e468905696191 --- /dev/null +++ b/solution/0900-0999/0973.K Closest Points to Origin/Solution3.go @@ -0,0 +1,29 @@ +func kClosest(points [][]int, k int) (ans [][]int) { + n := len(points) + dist := make([]int, n) + l, r := 0, 0 + for i, p := range points { + dist[i] = p[0]*p[0] + p[1]*p[1] + r = max(r, dist[i]) + } + for l < r { + mid := (l + r) >> 1 + cnt := 0 + for _, d := range dist { + if d <= mid { + cnt++ + } + } + if cnt >= k { + r = mid + } else { + l = mid + 1 + } + } + for i, p := range points { + if dist[i] <= l { + ans = append(ans, p) + } + } + return +} From 53480120adce229722f185c94f95dca615e6970a Mon Sep 17 00:00:00 2001 From: Libin YANG Date: Tue, 2 Jul 2024 20:06:39 +0800 Subject: [PATCH 18/23] Create Solution3.py --- .../0973.K Closest Points to Origin/Solution3.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 solution/0900-0999/0973.K Closest Points to Origin/Solution3.py diff --git a/solution/0900-0999/0973.K Closest Points to Origin/Solution3.py b/solution/0900-0999/0973.K Closest Points to Origin/Solution3.py new file mode 100644 index 0000000000000..8b85f5c63d0dc --- /dev/null +++ b/solution/0900-0999/0973.K Closest Points to Origin/Solution3.py @@ -0,0 +1,12 @@ +class Solution: + def kClosest(self, points: List[List[int]], k: int) -> List[List[int]]: + dist = [x * x + y * y for x, y in points] + l, r = 0, max(dist) + while l < r: + mid = (l + r) >> 1 + cnt = sum(d <= mid for d in dist) + if cnt >= k: + r = mid + else: + l = mid + 1 + return [points[i] for i, d in enumerate(dist) if d <= l] From a2f14cfa778b8727cade467cd0fbf4d2d45c4d22 Mon Sep 17 00:00:00 2001 From: Libin YANG Date: Tue, 2 Jul 2024 20:06:56 +0800 Subject: [PATCH 19/23] Update Solution.rs --- .../0973.K Closest Points to Origin/Solution.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/solution/0900-0999/0973.K Closest Points to Origin/Solution.rs b/solution/0900-0999/0973.K Closest Points to Origin/Solution.rs index e02f320342f94..72df73de1764e 100644 --- a/solution/0900-0999/0973.K Closest Points to Origin/Solution.rs +++ b/solution/0900-0999/0973.K Closest Points to Origin/Solution.rs @@ -1,7 +1,10 @@ impl Solution { pub fn k_closest(mut points: Vec>, k: i32) -> Vec> { - points - .sort_unstable_by(|a, b| (a[0].pow(2) + a[1].pow(2)).cmp(&(b[0].pow(2) + b[1].pow(2)))); - points[0..k as usize].to_vec() + points.sort_by(|a, b| { + let dist_a = f64::hypot(a[0] as f64, a[1] as f64); + let dist_b = f64::hypot(b[0] as f64, b[1] as f64); + dist_a.partial_cmp(&dist_b).unwrap() + }); + points.into_iter().take(k as usize).collect() } } From e8f334f7d7d443bf45efd7a884f4c2081d92df31 Mon Sep 17 00:00:00 2001 From: Libin YANG Date: Tue, 2 Jul 2024 20:07:23 +0800 Subject: [PATCH 20/23] Create Solution2.py --- .../0973.K Closest Points to Origin/Solution2.py | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 solution/0900-0999/0973.K Closest Points to Origin/Solution2.py diff --git a/solution/0900-0999/0973.K Closest Points to Origin/Solution2.py b/solution/0900-0999/0973.K Closest Points to Origin/Solution2.py new file mode 100644 index 0000000000000..40c1f46669b12 --- /dev/null +++ b/solution/0900-0999/0973.K Closest Points to Origin/Solution2.py @@ -0,0 +1,9 @@ +class Solution: + def kClosest(self, points: List[List[int]], k: int) -> List[List[int]]: + max_q = [] + for i, (x, y) in enumerate(points): + dist = math.hypot(x, y) + heappush(max_q, (-dist, i)) + if len(max_q) > k: + heappop(max_q) + return [points[i] for _, i in max_q] From bb7e20c207833a672913cbc7e295d5cee250304f Mon Sep 17 00:00:00 2001 From: Libin YANG Date: Tue, 2 Jul 2024 20:10:04 +0800 Subject: [PATCH 21/23] Update Solution.java --- .../0900-0999/0973.K Closest Points to Origin/Solution.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/solution/0900-0999/0973.K Closest Points to Origin/Solution.java b/solution/0900-0999/0973.K Closest Points to Origin/Solution.java index e84831659999b..87100bb269c33 100644 --- a/solution/0900-0999/0973.K Closest Points to Origin/Solution.java +++ b/solution/0900-0999/0973.K Closest Points to Origin/Solution.java @@ -1,6 +1,7 @@ class Solution { public int[][] kClosest(int[][] points, int k) { - Arrays.sort(points, (p1, p2) -> Math.hypot(p1[0], p1[1]) - Math.hypot(p2[0], p2[1]) > 0 ? 1 : -1); + Arrays.sort( + points, (p1, p2) -> Math.hypot(p1[0], p1[1]) - Math.hypot(p2[0], p2[1]) > 0 ? 1 : -1); return Arrays.copyOfRange(points, 0, k); } } From d80e291a826aa46506bc23088c1ba4d3445147f2 Mon Sep 17 00:00:00 2001 From: Libin YANG Date: Tue, 2 Jul 2024 20:10:18 +0800 Subject: [PATCH 22/23] Update README.md --- solution/0900-0999/0973.K Closest Points to Origin/README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/solution/0900-0999/0973.K Closest Points to Origin/README.md b/solution/0900-0999/0973.K Closest Points to Origin/README.md index a9c88c3d89b72..d2c088e0e15aa 100644 --- a/solution/0900-0999/0973.K Closest Points to Origin/README.md +++ b/solution/0900-0999/0973.K Closest Points to Origin/README.md @@ -89,7 +89,8 @@ class Solution: ```java class Solution { public int[][] kClosest(int[][] points, int k) { - Arrays.sort(points, (p1, p2) -> Math.hypot(p1[0], p1[1]) - Math.hypot(p2[0], p2[1]) > 0 ? 1 : -1); + Arrays.sort( + points, (p1, p2) -> Math.hypot(p1[0], p1[1]) - Math.hypot(p2[0], p2[1]) > 0 ? 1 : -1); return Arrays.copyOfRange(points, 0, k); } } From bbe381e2db56927f8cfe60ffba4671c7900eead6 Mon Sep 17 00:00:00 2001 From: Libin YANG Date: Tue, 2 Jul 2024 20:10:31 +0800 Subject: [PATCH 23/23] Update README_EN.md --- .../0900-0999/0973.K Closest Points to Origin/README_EN.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/solution/0900-0999/0973.K Closest Points to Origin/README_EN.md b/solution/0900-0999/0973.K Closest Points to Origin/README_EN.md index a7257ca6ce307..6a79fa85e7dc4 100644 --- a/solution/0900-0999/0973.K Closest Points to Origin/README_EN.md +++ b/solution/0900-0999/0973.K Closest Points to Origin/README_EN.md @@ -85,7 +85,8 @@ class Solution: ```java class Solution { public int[][] kClosest(int[][] points, int k) { - Arrays.sort(points, (p1, p2) -> Math.hypot(p1[0], p1[1]) - Math.hypot(p2[0], p2[1]) > 0 ? 1 : -1); + Arrays.sort( + points, (p1, p2) -> Math.hypot(p1[0], p1[1]) - Math.hypot(p2[0], p2[1]) > 0 ? 1 : -1); return Arrays.copyOfRange(points, 0, k); } }