Skip to content

Commit fc715c0

Browse files
committed
add #658 version 2
1 parent b9d57f1 commit fc715c0

File tree

1 file changed

+82
-0
lines changed

1 file changed

+82
-0
lines changed
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
"""
2+
Given a sorted integer array arr, two integers k and x, return the k
3+
closest integers to x in the array. The result should also be sorted
4+
in ascending order.
5+
6+
An integer a is closer to x than an integer b if:
7+
|a - x| < |b - x|, or
8+
|a - x| == |b - x| and a < b
9+
-------
10+
- Probably a linear time solution? Only need to look at every val once.
11+
- Can use a maxheap - push tuples in of (distance from x, val); heapify on first value, only
12+
push new elements when max distance from x is greater than current element's.
13+
- Input array is sorted, so can we do better?
14+
- Could find index / insertion point for x in arr, then
15+
use two pointers to keep track of k nearest elements - O(log(N)) + K where N = len(arr)
16+
-----------
17+
ret = collections.deque()
18+
insertion_point = bin_search(arr, x)
19+
if arr[insertion_point] <= x:
20+
lower, higher = insertion_point, insertion_point+1
21+
else:
22+
lower, higher = insertion_point-1, insertion_point
23+
while len(ret) < k and (lower >= 0 or higher < len(arr)):
24+
if higher >= len(arr) or distance(x, arr[lower]) <= distance(x, arr[higher]):
25+
ret.appendleft(arr[lower])
26+
lower -= 1
27+
else:
28+
ret.append(arr[higher])
29+
higher+=1
30+
return ret
31+
"""
32+
from collections import deque
33+
from typing import List
34+
35+
def bin_search(arr, val):
36+
lo, hi = 0, len(arr)-1
37+
while lo <= hi:
38+
mid = (hi + lo) // 2
39+
if arr[mid] == val:
40+
return mid
41+
elif arr[mid] > val:
42+
lo, hi = lo, mid - 1
43+
else:
44+
lo, hi = mid+1, hi
45+
return lo
46+
47+
class Solution:
48+
def findClosestElements(self, arr: List[int], k: int, x: int) -> List[int]:
49+
ret = deque()
50+
insertion_point = bin_search(arr, x)
51+
if insertion_point < len(arr) and arr[insertion_point] <= x:
52+
lower, higher = insertion_point, insertion_point+1
53+
else:
54+
lower, higher = insertion_point-1, insertion_point
55+
while len(ret) < k and (lower >= 0 or higher < len(arr)):
56+
if higher >= len(arr) or abs(x - arr[lower]) <= abs(x - arr[higher]):
57+
ret.appendleft(arr[lower])
58+
lower -= 1
59+
else:
60+
ret.append(arr[higher])
61+
higher+=1
62+
return list(ret)
63+
64+
s = Solution()
65+
for case in [
66+
# lower will go below 0
67+
([1,2,3,4,5], 4, 0, [1,2,3,4]),
68+
# higher will go above last element
69+
([1,2,3,4,5], 4, 6, [2,3,4,5]),
70+
# len(arr) == k
71+
([1,2,3,4,5], 5, 9, [1,2,3,4,5]),
72+
# x not in arr
73+
([1,2,3,4,5], 4, -1, [1,2,3,4]),
74+
# x in arr
75+
([1,2,3,4,5], 4, 3, [1,2,3,4]),
76+
# previous failures
77+
([1,1,2,2,2,2,2,3,3], 3, 3, [2,3,3])
78+
]:
79+
arr, k, x, ans = case
80+
print(arr, k, x)
81+
actual = s.findClosestElements(arr, k, x)
82+
assert actual == ans, (arr, k, x, ans, actual)

0 commit comments

Comments
 (0)