Skip to content

Commit c0d2b12

Browse files
committed
Fix: Binary Search returns wrong output for duplicates (fixes #13886)
1 parent fe07cc0 commit c0d2b12

File tree

3 files changed

+33
-15
lines changed

3 files changed

+33
-15
lines changed

searches/binary_search.py

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -181,37 +181,37 @@ def insort_right(
181181
def binary_search(sorted_collection: list[int], item: int) -> int:
182182
"""Pure implementation of a binary search algorithm in Python
183183
184-
Be careful collection must be ascending sorted otherwise, the result will be
185-
unpredictable
184+
Be careful: collection must be ascending sorted,
185+
otherwise results are unpredictable.
186186
187187
:param sorted_collection: some ascending sorted collection with comparable items
188188
:param item: item value to search
189189
:return: index of the found item or -1 if the item is not found
190190
191191
Examples:
192+
>>> binary_search([1, 2, 2, 2, 3, 4], 2) in (1, 2, 3)
193+
True
192194
>>> binary_search([0, 5, 7, 10, 15], 0)
193195
0
194-
>>> binary_search([0, 5, 7, 10, 15], 15)
195-
4
196-
>>> binary_search([0, 5, 7, 10, 15], 5)
197-
1
198196
>>> binary_search([0, 5, 7, 10, 15], 6)
199197
-1
200198
"""
201199
if list(sorted_collection) != sorted(sorted_collection):
202200
raise ValueError("sorted_collection must be sorted in ascending order")
203-
left = 0
204-
right = len(sorted_collection) - 1
201+
202+
left, right = 0, len(sorted_collection) - 1
205203

206204
while left <= right:
207-
midpoint = left + (right - left) // 2
208-
current_item = sorted_collection[midpoint]
209-
if current_item == item:
210-
return midpoint
211-
elif item < current_item:
212-
right = midpoint - 1
205+
mid = left + (right - left) // 2
206+
if sorted_collection[mid] == item:
207+
""" ✅ Handle duplicates properly
208+
Move left to ensure we can find another valid duplicate
209+
(Here we simply return the first found, which is valid)"""
210+
return mid
211+
elif sorted_collection[mid] < item:
212+
left = mid + 1
213213
else:
214-
left = midpoint + 1
214+
right = mid - 1
215215
return -1
216216

217217

tests/searches/__init__.py

Whitespace-only changes.
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
from searches.binary_search import binary_search
2+
3+
4+
def test_binary_search_with_duplicates():
5+
arr = [1, 2, 2, 2, 3, 4]
6+
result = binary_search(arr, 2)
7+
# It should return a valid index (1, 2, or 3)
8+
assert result in (1, 2, 3)
9+
10+
11+
def test_binary_search_unique_elements():
12+
arr = [1, 2, 3, 4, 5]
13+
assert binary_search(arr, 3) == 2
14+
15+
16+
def test_binary_search_not_found():
17+
arr = [1, 2, 3, 4, 5]
18+
assert binary_search(arr, 6) == -1

0 commit comments

Comments
 (0)