@@ -12,4 +12,120 @@ def kClosest(self, points, k):
1212 else :
1313 heapq .heappush (h , (- d , x , y ))
1414
15- return [(x , y ) for _ , x , y in h ]
15+ return [(x , y ) for _ , x , y in h ]
16+
17+
18+ """
19+ 1. Process `points` into `distances`.
20+
21+ 2. Binary search the "distance". For every distance:
22+ Split the elements in `distances` by distance
23+ Put the ones smaller to smaller.
24+ Put the ones larger to larger.
25+ If len(smaller)<=k, then all the elements in the smaller must belong to the `ans`, do the same thing to the larger.
26+ Else we ignore the larger and do the same thing to the smaller again.
27+
28+ Time: O(N)
29+ The binary search range in average is N, N/2, N/4... = 2N
30+ Space: O(N)
31+ """
32+ class Solution (object ):
33+ def kClosest (self , points , K ):
34+ #[1]
35+ maxD = float ('-inf' )
36+ minD = float ('inf' )
37+ distances = []
38+ for x , y in points :
39+ distance = ((x ** 2 + y ** 2 )** 0.5 )
40+ distances .append ((distance , x , y ))
41+ maxD = max (maxD , distance )
42+ minD = min (minD , distance )
43+
44+ #[2]
45+ ans = []
46+ smaller = []
47+ larger = []
48+ while K > 0 :
49+ #split distances into smaller and larger
50+ distance = (maxD + minD )/ 2
51+ for d , x , y in distances :
52+ if d <= distance :
53+ smaller .append ((d , x , y ))
54+ else :
55+ larger .append ((d , x , y ))
56+
57+ if len (smaller )<= K :
58+ ans += smaller
59+ K -= len (smaller )
60+ distances = larger
61+ minD = distance
62+ larger = []
63+ smaller = []
64+ else :
65+ distances = smaller
66+ maxD = distance
67+ larger = []
68+ smaller = []
69+
70+ return [(x , y ) for _ , x , y in ans ]
71+
72+
73+
74+ """
75+ Quick Select
76+ Time: O(N)
77+ Space: O(N), can be optimize to O(1).
78+ """
79+ class Solution (object ):
80+ def kClosest (self , points , K ):
81+ """
82+ Start State:
83+ i = s #next element after "SSS"s
84+ t = s #unprocessed elements
85+ j = e #next element after "LLLL"s
86+
87+ SSSPP?????LLL
88+ i t j
89+
90+ End State:
91+ SSSPPPPPLLLLL
92+ i jt
93+ """
94+ def quickSelect (distances , s , e , k ):
95+
96+ pivot = distances [(s + e )/ 2 ][0 ]
97+ i = s
98+ j = e
99+ t = s
100+
101+ while t <= j :
102+ if pivot < distances [t ][0 ]:
103+ distances [t ], distances [j ] = distances [j ], distances [t ]
104+ j -= 1
105+ elif pivot > distances [t ][0 ]:
106+ distances [t ], distances [i ] = distances [i ], distances [t ]
107+ i += 1
108+ t += 1
109+ else :
110+ t += 1
111+
112+ if i - s >= k :
113+ return quickSelect (distances , s , i , k )
114+ elif j - s + 1 >= k :
115+ return pivot
116+ else :
117+ return quickSelect (distances , t , e , k - (t - s ))
118+
119+ distances = []
120+ for x , y in points :
121+ distance = ((x ** 2 + y ** 2 )** 0.5 )
122+ distances .append ((distance , x , y ))
123+
124+ kthSmallestDistance = quickSelect (distances , 0 , len (distances )- 1 , K )
125+
126+ ans = []
127+ for d , x , y in distances :
128+ if len (ans )== K : break
129+ if d <= kthSmallestDistance : ans .append ((x , y ))
130+
131+ return ans
0 commit comments