Skip to content

Commit c14fd10

Browse files
committed
Time: 55 ms (83.75%), Space: 22.2 MB (81.53%) - LeetHub
1 parent 3499bfc commit c14fd10

File tree

1 file changed

+110
-0
lines changed

1 file changed

+110
-0
lines changed
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
from heapq import heapify, heappop, heappush
2+
from math import sqrt
3+
from typing import List
4+
5+
# time complexity: O(nlogk)
6+
# space complexity: O(k)
7+
class Solution:
8+
def kClosest(self, points: List[List[int]], k: int) -> List[List[int]]:
9+
maxHp = [(-(x ** 2 + y ** 2), x, y) for x, y in points[:k]]
10+
heapify(maxHp)
11+
for currX, currY in points[k:]:
12+
dist = -(currX ** 2 + currY ** 2)
13+
if dist > maxHp[0][0]:
14+
heappop(maxHp)
15+
heappush(maxHp, (dist, currX, currY))
16+
17+
return [[x, y] for _, x, y in maxHp]
18+
19+
# time complexity: O(nlogn)
20+
# space complexity: O(k)
21+
class Solution:
22+
def kClosest(self, points: List[List[int]], k: int) -> List[List[int]]:
23+
minHeap = [(sqrt(x**2 + y**2), x, y) for x, y in points]
24+
heapify(minHeap)
25+
result = []
26+
while k:
27+
_, currX, currY = heappop(minHeap)
28+
result.append([currX, currY])
29+
k -= 1
30+
return result
31+
32+
# time complexity: O(n)
33+
# space complexity: O(n)
34+
class Solution:
35+
def kClosest(self, points: List[List[int]], k: int) -> List[List[int]]:
36+
distances = [self.distance(point) for point in points]
37+
remaining = [i for i in range(len(points))]
38+
left, right = 0, max(distances)
39+
40+
closest = []
41+
while k:
42+
mid = (left + right) // 2
43+
closer, farther = self.splitDis(remaining, distances, mid)
44+
if len(closer) > k:
45+
remaining = closer
46+
right = mid
47+
else:
48+
k -= len(closer)
49+
closest.extend(closer)
50+
remaining = farther
51+
left = mid
52+
return [points[i] for i in closest]
53+
54+
def splitDis(self, remaining: List[int], distances: List[float],
55+
mid: int) -> List[List[int]]:
56+
closer, farther = [], []
57+
for index in remaining:
58+
if distances[index] <= mid:
59+
closer.append(index)
60+
else:
61+
farther.append(index)
62+
return [closer, farther]
63+
64+
def distance(self, point: List[int]) -> float:
65+
return point[0] ** 2 + point[1] ** 2
66+
67+
# time complexity: O(n)
68+
# space complexity: O(1)
69+
class Solution:
70+
def kClosest(self, points: List[List[int]], k: int) -> List[List[int]]:
71+
return self.quickSelect(points, k)
72+
73+
def quickSelect(self, points: List[List[int]], k: int) -> List[List[int]]:
74+
left, right = 0, len(points) - 1
75+
pivotIdx = len(points)
76+
while pivotIdx != k:
77+
pivotIdx = self.partition(points, left, right)
78+
if pivotIdx < k:
79+
left = pivotIdx
80+
else:
81+
right = pivotIdx - 1
82+
83+
return points[:k]
84+
85+
def partition(self, points: List[List[int]], left: int, right: int) -> int:
86+
pivot = self.choosePivot(points, left, right)
87+
pivotDis = self.distance(pivot)
88+
while left < right:
89+
if self.distance(points[left]) >= pivotDis:
90+
points[left], points[right] = points[right], points[left]
91+
right -= 1
92+
else:
93+
left += 1
94+
95+
if self.distance(points[left]) < pivotDis:
96+
left += 1
97+
return left
98+
99+
def choosePivot(self, points: List[List[int]], left: int, right: int) -> List[int]:
100+
return points[left + (right - left) // 2]
101+
102+
def distance(self, point: List[int]) -> int:
103+
return point[0] ** 2 + point[1] ** 2
104+
105+
points = [[1, 3], [-2, 2]]
106+
k = 1
107+
print(Solution().kClosest(points, k))
108+
points = [[3, 3], [5, -1], [-2, 4]]
109+
k = 2
110+
print(Solution().kClosest(points, k))

0 commit comments

Comments
 (0)