Skip to content

Commit 6b4d9d9

Browse files
committed
Fix binary search to return first occurrence when duplicates exist
1 parent f527d43 commit 6b4d9d9

File tree

1 file changed

+14
-9
lines changed

1 file changed

+14
-9
lines changed

searches/binary_search.py

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -202,17 +202,19 @@ def binary_search(sorted_collection: list[int], item: int) -> int:
202202
raise ValueError("sorted_collection must be sorted in ascending order")
203203
left = 0
204204
right = len(sorted_collection) - 1
205+
result = -1
205206

206207
while left <= right:
207208
midpoint = left + (right - left) // 2
208209
current_item = sorted_collection[midpoint]
209210
if current_item == item:
210-
return midpoint
211+
result = midpoint
212+
right = midpoint - 1
211213
elif item < current_item:
212214
right = midpoint - 1
213215
else:
214216
left = midpoint + 1
215-
return -1
217+
return result
216218

217219

218220
def binary_search_std_lib(sorted_collection: list[int], item: int) -> int:
@@ -319,7 +321,7 @@ def upper_bound(sorted_collection: list[int], item: int) -> int:
319321

320322

321323
def binary_search_by_recursion(
322-
sorted_collection: list[int], item: int, left: int = 0, right: int = -1
324+
sorted_collection: list[int], item: int, left: int = 0, right: int | None = None
323325
) -> int:
324326
"""Pure implementation of a binary search algorithm in Python by recursion
325327
@@ -332,16 +334,16 @@ def binary_search_by_recursion(
332334
:return: index of the found item or -1 if the item is not found
333335
334336
Examples:
335-
>>> binary_search_by_recursion([0, 5, 7, 10, 15], 0, 0, 4)
337+
>>> binary_search_by_recursion([0, 5, 7, 10, 15], 0)
336338
0
337-
>>> binary_search_by_recursion([0, 5, 7, 10, 15], 15, 0, 4)
339+
>>> binary_search_by_recursion([0, 5, 7, 10, 15], 15)
338340
4
339-
>>> binary_search_by_recursion([0, 5, 7, 10, 15], 5, 0, 4)
341+
>>> binary_search_by_recursion([0, 5, 7, 10, 15], 5)
340342
1
341-
>>> binary_search_by_recursion([0, 5, 7, 10, 15], 6, 0, 4)
343+
>>> binary_search_by_recursion([0, 5, 7, 10, 15], 6)
342344
-1
343345
"""
344-
if right < 0:
346+
if right is None:
345347
right = len(sorted_collection) - 1
346348
if list(sorted_collection) != sorted(sorted_collection):
347349
raise ValueError("sorted_collection must be sorted in ascending order")
@@ -351,7 +353,10 @@ def binary_search_by_recursion(
351353
midpoint = left + (right - left) // 2
352354

353355
if sorted_collection[midpoint] == item:
354-
return midpoint
356+
left_result = binary_search_by_recursion(
357+
sorted_collection, item, left, midpoint - 1
358+
)
359+
return left_result if left_result != -1 else midpoint
355360
elif sorted_collection[midpoint] > item:
356361
return binary_search_by_recursion(sorted_collection, item, left, midpoint - 1)
357362
else:

0 commit comments

Comments
 (0)