@@ -186,7 +186,9 @@ def binary_search(sorted_collection: list[int], item: int) -> int:
186186
187187 :param sorted_collection: some ascending sorted collection with comparable items
188188 :param item: item value to search
189- :return: index of the found item or -1 if the item is not found
189+ :return: index of the found item or -1 if the item is not found.
190+ If there are multiple occurrences of the item, returns the index
191+ of the leftmost occurrence.
190192
191193 Examples:
192194 >>> binary_search([0, 5, 7, 10, 15], 0)
@@ -197,22 +199,28 @@ def binary_search(sorted_collection: list[int], item: int) -> int:
197199 1
198200 >>> binary_search([0, 5, 7, 10, 15], 6)
199201 -1
202+ >>> binary_search([1, 2, 4, 4, 4, 6, 7], 4)
203+ 2
204+ >>> binary_search([0, 5, 7, 10, 10, 10], 10)
205+ 3
200206 """
201207 if list (sorted_collection ) != sorted (sorted_collection ):
202208 raise ValueError ("sorted_collection must be sorted in ascending order" )
203209 left = 0
204210 right = len (sorted_collection ) - 1
211+ result = - 1
205212
206213 while left <= right :
207214 midpoint = left + (right - left ) // 2
208215 current_item = sorted_collection [midpoint ]
209216 if current_item == item :
210- return midpoint
217+ result = midpoint # Found the item, but continue to find leftmost occurrence
218+ right = midpoint - 1 # Look for more occurrences on the left
211219 elif item < current_item :
212220 right = midpoint - 1
213221 else :
214222 left = midpoint + 1
215- return - 1
223+ return result
216224
217225
218226def binary_search_std_lib (sorted_collection : list [int ], item : int ) -> int :
@@ -254,7 +262,9 @@ def binary_search_by_recursion(
254262
255263 :param sorted_collection: some ascending sorted collection with comparable items
256264 :param item: item value to search
257- :return: index of the found item or -1 if the item is not found
265+ :return: index of the found item or -1 if the item is not found.
266+ If there are multiple occurrences of the item, returns the index
267+ of the leftmost occurrence.
258268
259269 Examples:
260270 >>> binary_search_by_recursion([0, 5, 7, 10, 15], 0, 0, 4)
@@ -265,22 +275,35 @@ def binary_search_by_recursion(
265275 1
266276 >>> binary_search_by_recursion([0, 5, 7, 10, 15], 6, 0, 4)
267277 -1
278+ >>> binary_search_by_recursion([1, 2, 4, 4, 4, 6, 7], 4, 0, 6)
279+ 2
280+ >>> binary_search_by_recursion([0, 5, 7, 10, 10, 10], 10, 0, 5)
281+ 3
268282 """
269283 if right < 0 :
270284 right = len (sorted_collection ) - 1
271285 if list (sorted_collection ) != sorted (sorted_collection ):
272286 raise ValueError ("sorted_collection must be sorted in ascending order" )
273- if right < left :
274- return - 1
287+
288+ # Helper function for the binary search
289+ def _binary_search_recursive (left_idx : int , right_idx : int ) -> int :
290+ if right_idx < left_idx :
291+ return - 1
275292
276- midpoint = left + (right - left ) // 2
293+ midpoint = left_idx + (right_idx - left_idx ) // 2
294+ current_item = sorted_collection [midpoint ]
277295
278- if sorted_collection [midpoint ] == item :
279- return midpoint
280- elif sorted_collection [midpoint ] > item :
281- return binary_search_by_recursion (sorted_collection , item , left , midpoint - 1 )
282- else :
283- return binary_search_by_recursion (sorted_collection , item , midpoint + 1 , right )
296+ if current_item == item :
297+ # Found the item, now find the leftmost occurrence
298+ # First, recursively find any occurrence to the left
299+ leftmost = _binary_search_recursive (left_idx , midpoint - 1 )
300+ return leftmost if leftmost != - 1 else midpoint
301+ elif item < current_item :
302+ return _binary_search_recursive (left_idx , midpoint - 1 )
303+ else :
304+ return _binary_search_recursive (midpoint + 1 , right_idx )
305+
306+ return _binary_search_recursive (left , right )
284307
285308
286309def exponential_search (sorted_collection : list [int ], item : int ) -> int :
0 commit comments