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..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 @@ -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,8 @@ 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 +102,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 +115,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 +125,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,10 +135,309 @@ 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() + } +} +``` + + + + + + + +### 方法二:优先队列(大根堆) + +我们可以使用一个优先队列(大根堆)来维护距离原点最近的 $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 maxQ = new MaxPriorityQueue(); + for (const [x, y] of points) { + const dist = x * x + y * y; + maxQ.enqueue([x, y], dist); + if (maxQ.size() > k) { + maxQ.dequeue(); + } + } + return maxQ.toArray().map(item => item.element); +} +``` + + + + + + + +### 方法三:二分查找 + +我们注意到,随着距离的增大,点的数量是递增的。这存在一个临界值,使得在这个值之前的点的数量小于等于 $k$,而在这个值之后的点的数量大于 $k$。 + +因此,我们可以使用二分查找,枚举距离。每一次二分查找,我们统计出距离小于等于当前距离的点的数量,如果数量大于等于 $k$,则说明临界值在左侧,我们令右边界等于当前距离;否则,临界值在右侧,我们令左边界等于当前距禽加一。 + +二分查找结束后,我们只需要返回距离小于等于左边界的点即可。 + +时间复杂度 $O(n \times \log M)$,空间复杂度 $O(n)$。其中 $n$ 为数组 $\text{points}$ 的长度,而 $M$ 为距离的最大值。 + + + +#### Python3 + +```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] +``` + +#### Java + +```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++ + +```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 + +```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; + } else { + l = mid + 1; + } } + return points.filter((_, i) => dist[i] <= l); } ``` 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..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 @@ -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,8 @@ 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 +98,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 +111,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 +121,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,10 +131,309 @@ 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() + } +} +``` + + + + + + + +### 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 maxQ = new MaxPriorityQueue(); + for (const [x, y] of points) { + const dist = x * x + y * y; + maxQ.enqueue([x, y], dist); + if (maxQ.size() > k) { + maxQ.dequeue(); + } + } + return maxQ.toArray().map(item => item.element); +} +``` + + + + + + + +### 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. + + + +#### Python3 + +```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] +``` + +#### Java + +```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++ + +```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 + +```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; + } else { + l = mid + 1; + } } + return points.filter((_, i) => dist[i] <= l); } ``` 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 +}; 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 +} 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..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,10 +1,7 @@ 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 +} 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] 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() } } 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); } 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; + } +}; 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 } 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; + } +} 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] 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..afeb1c9d648f6 --- /dev/null +++ b/solution/0900-0999/0973.K Closest Points to Origin/Solution2.ts @@ -0,0 +1,11 @@ +function kClosest(points: number[][], k: number): number[][] { + const maxQ = new MaxPriorityQueue(); + for (const [x, y] of points) { + const dist = x * x + y * y; + maxQ.enqueue([x, y], dist); + if (maxQ.size() > k) { + maxQ.dequeue(); + } + } + return maxQ.toArray().map(item => item.element); +} 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; + } +}; 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 +} 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; + } +} 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] 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..47e00c9ffadbf --- /dev/null +++ b/solution/0900-0999/0973.K Closest Points to Origin/Solution3.ts @@ -0,0 +1,19 @@ +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; + } else { + l = mid + 1; + } + } + return points.filter((_, i) => dist[i] <= l); +}