Binary Search
I am a beginner coder who wants to keep track of my coding progress. I will post my LeetCode solutions here. Please feel free to give me advice or suggestions on my code.
Also, in the future, I will be posing my data science-related project here as well
When implementing binary search, the choice between using l <= r vs. l < r, and how to update l and r (l = mid + 1 vs. l = mid, etc.), depends on the specific problem and whether you are looking for an exact match, the lower bound, or the upper bound of a target value. Here's a breakdown of each scenario:
1. Basic Binary Search for Exact Match
Use case: Finding the exact position of a target element.
Loop condition:
while l <= rMid calculation:
mid = l + (r - l) // 2Updates:
If the target is found: return
midIf the target is less than the middle element:
r = mid - 1If the target is greater than the middle element:
l = mid + 1
def binary_search(arr, target):
l, r = 0, len(arr) - 1
while l <= r:
mid = l + (r - l) // 2
if arr[mid] == target:
return mid
elif arr[mid] < target:
l = mid + 1
else:
r = mid - 1
return -1 # target not found
Why
l <= r? The loop needs to continue as long as there are elements to check. Whenlequalsr,midwill still represent a valid index to check.Why
l = mid + 1andr = mid - 1? To move past the middle element after determining which side of the array the target could be in.
2. Finding the Lower Bound (First Occurrence)
Use case: Finding the first occurrence of a target value or the smallest value that is greater than or equal to the target.
Loop condition:
while l < rMid calculation:
mid = l + (r - l) // 2Updates:
If the mid value is greater than or equal to the target:
r = midIf the mid value is less than the target:
l = mid + 1
def lower_bound(arr, target):
l, r = 0, len(arr)
while l < r:
mid = l + (r - l) // 2
if arr[mid] < target:
l = mid + 1
else:
r = mid
return l
Why
l < r? This ensures that when the loop exits,lwill be the smallest index such thatarr[l]is greater than or equal to the target.Why
r = midand notmid - 1? When searching for the lower bound, ifarr[mid]is not less than the target, we cannot excludemidfrom being the potential lower bound.
3. Finding the Upper Bound (Last Occurrence)
Use case: Finding the last occurrence of a target value or the largest value that is less than or equal to the target.
Loop condition:
while l < rMid calculation:
mid = l + (r - l + 1) // 2(ormid = (l + r + 1) // 2)Updates:
If the mid value is less than or equal to the target:
l = midIf the mid value is greater than the target:
r = mid - 1
def upper_bound(arr, target):
l, r = 0, len(arr) - 1
while l < r:
mid = l + (r - l + 1) // 2
if arr[mid] > target:
r = mid - 1
else:
l = mid
return l
Why
l < r? The loop exits whenlequalsr, andlwill point to the largest index wherearr[l]is less than or equal to the target.Why
l = midand notmid + 1? When finding the upper bound, ifarr[mid]is less than or equal to the target, we cannot excludemidfrom potentially being the upper bound.
Summary
while l <= r: Use when you need to check every element and the target could be at any position, including whenl == r. This is common when searching for an exact match.while l < r: Use when searching for a boundary condition (like lower or upper bounds). This setup ensures thatlends at the boundary condition.l = mid + 1vs.r = mid - 1: Use when you can safely excludemidfrom the next search range (e.g., exact search when the target is not atmid).l = midvs.r = mid: Use whenmidcould still be the target or part of the desired result (e.g., when looking for a boundary).