Binary Search
š§ Spot It
Use Binary Search when:
- Input is sorted (array, range, search space)
- Problem asks for a specific value, or min/max that satisfies a condition
- Brute force is O(N) or O(N²) ā binary search brings it to O(log N)
Key insight: Binary search isn't just for sorted arrays ā it's a search space reduction tool.
Pattern 1 ā Classic Binary Search
Find a target in a sorted array.
def binary_search(arr, target):
left, right = 0, len(arr) - 1
while left <= right:
mid = left + (right - left) // 2 # avoid overflow
if arr[mid] == target:
return mid
elif arr[mid] < target:
left = mid + 1
else:
right = mid - 1
return -1
Pattern 2 ā Find Boundary (leftmost / rightmost)
Used when duplicates exist or you need first/last occurrence.
def find_left_boundary(arr, target):
left, right = 0, len(arr) - 1
result = -1
while left <= right:
mid = left + (right - left) // 2
if arr[mid] == target:
result = mid
right = mid - 1 # keep searching left
elif arr[mid] < target:
left = mid + 1
else:
right = mid - 1
return result
Pattern 3 ā Binary Search on Answer (Search Space)
Problem gives a range of possible answers ā binary search the answer space.
Template:
def binary_search_answer(lo, hi):
result = -1
while lo <= hi:
mid = lo + (hi - lo) // 2
if is_feasible(mid): # define your condition
result = mid
hi = mid - 1 # or lo = mid + 1 depending on min/max
else:
lo = mid + 1
return result
Classic example: Koko Eating Bananas ā binary search on eating speed, check if feasible.
Pattern 4 ā Rotated Sorted Array
Array was sorted then rotated at unknown pivot. Determine which half is sorted, then decide where target lives.
# LC 33 ā Search in Rotated Sorted Array
def search(nums, target):
left, right = 0, len(nums) - 1
while left <= right:
mid = left + (right - left) // 2
if nums[mid] == target:
return mid
# Left half is sorted
if nums[left] <= nums[mid]:
if nums[left] <= target < nums[mid]:
right = mid - 1 # target in sorted left half
else:
left = mid + 1 # target in right half
# Right half is sorted
else:
if nums[mid] < target <= nums[right]:
left = mid + 1 # target in sorted right half
else:
right = mid - 1 # target in left half
return -1
Key insight: One half is always sorted. Check which ā then determine if target falls in that sorted range. If yes, search there; if not, search the other half.
Pattern 5 ā Peak Element / Find Minimum in Rotated
# LC 153 ā Find Minimum in Rotated Sorted Array
def findMin(nums):
left, right = 0, len(nums) - 1
while left < right: # NOT <=
mid = left + (right - left) // 2
if nums[mid] > nums[right]:
left = mid + 1 # min is in right half
else:
right = mid # mid might BE the min ā don't exclude it
return nums[left]
Key insight: Compare mid to right (not left). If nums[mid] > nums[right], the rotation happened in the right half so min is there. Otherwise min is in left half (mid could be it, so right = mid not mid - 1).
Python bisect Module
import bisect
# bisect_left: index of first element >= target
# bisect_right: index of first element > target
arr = [1, 3, 3, 5, 7]
bisect.bisect_left(arr, 3) # 1 (first 3)
bisect.bisect_right(arr, 3) # 3 (after last 3)
# Insert into sorted position
bisect.insort(arr, 4) # arr = [1, 3, 3, 4, 5, 7]
Use bisect_left when you want leftmost position (first occurrence, lower_bound).
Use bisect_right when you want rightmost position (after last occurrence, upper_bound).
Interview Opener
"I'll binary search the answer space ā define lo/hi as the range of possible answers, define a feasibility check, and shrink the range each iteration to O(log N)."
Senior Tricks
mid = left + (right - left) // 2ā never(left + right) // 2(overflow risk in other langs)while left < rightvsleft <= right: Use<=when you return inside the loop on==. Use<when you narrow without a direct return (find min/max position).right = midvsright = mid - 1: Usemidwhenmiditself could be the answer (don't exclude it). Usemid - 1whenmidis confirmed NOT the answer.
Problems
| # | Problem | Pattern | Link | Status |
|---|---|---|---|---|
| 1 | Binary Search | Classic | LC 704 | ā W04 |
| 2 | Search a 2D Matrix | Classic | LC 74 | ā W04 |
| 3 | Find Minimum in Rotated Sorted Array | Rotated | LC 153 | ā W04 |
| 4 | Search in Rotated Sorted Array | Rotated | LC 33 | ā W04 |
| 5 | Time Based Key-Value Store | Boundary | LC 981 | ā W04 |
| 6 | Koko Eating Bananas | Search Space | LC 875 | ā W04 |
| 7 | Median of Two Sorted Arrays | Hard | LC 4 | ⬠Deferred ā revisit after Linked Lists |