Skip to main content

Binary Search Fundamentals

TL;DR

Binary search eliminates half the search space each iteration on sorted arrays, achieving O(log n) time. Standard template uses left and right pointers, comparing mid to target. Two key patterns: finding element (left <= right) and finding boundary (left < right). Off-by-one errors are common: loop condition (< vs <=), mid calculation (left + (right - left) / 2 avoids overflow), return value (left, right, or -1/not found) must match intent. Master template prevents subtle bugs.

Core Concepts

Binary Search Template

Standard pattern: left = 0, right = n - 1. While left <= right: mid = (left + right) // 2. If arr[mid] == target, return mid. If arr[mid] < target, left = mid + 1. Else right = mid - 1. Return -1 if not found.

Left/right differences: left <= right continues until pointers cross; left < right stops when equal. Choose based on whether searching for exact match or boundary.

Mid calculation: mid = left + (right - left) // 2 prevents overflow compared to (left + right) // 2 in languages without arbitrary precision.

Left Bound and Right Bound

Left bound finds first occurrence of target. After finding target, continue left search to find first. Template: when arr[mid] >= target, move right = mid - 1 (include mid, might be first).

Right bound finds last occurrence of target. When arr[mid] <= target, move left = mid + 1 (include mid, might be last).

Both bounds combined answer "is element present" (left bound < n and arr[left] == target), "count occurrences" (right bound - left bound + 1).

Off-by-One Errors

Loop condition: < vs <= changes meaning. <= searches until pointers overlap; < searches for exact boundary where left/right stabilize.

Mid rounding: mid = (left + right) // 2 rounds down. Affects whether left or right half biased. Mid calculation affects loop termination and final answer.

Return value: returning mid vs left vs right or -1. After loop, left and right diverge. left typically points to insertion point for missing element.

Boundary conditions: arrays of size 0 or 1 require special handling. Empty array returns -1. Single element compares and returns 0 or -1.

Key Algorithms and Techniques

Standard Exact Match Template

left <= right loop, eliminate half each iteration.

Find first occurrence by continuing left search.

Find last occurrence by continuing right search.

Insertion Point Finding

Return left when element not found (indicates insertion position).

Practical Example

# Standard binary search
def binarySearch(arr, target):
left, right = 0, len(arr) - 1
while left <= right:
mid = left + (right - left) // 2
if arr[mid] == target:
return mid
elif arr[mid] < target:
left = mid + 1
else:
right = mid - 1
return -1

# Find left bound (first occurrence)
def leftBound(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 # Continue left
elif arr[mid] < target:
left = mid + 1
else:
right = mid - 1
return result

# Find right bound (last occurrence)
def rightBound(arr, target):
left, right = 0, len(arr) - 1
result = -1
while left <= right:
mid = left + (right - left) // 2
if arr[mid] == target:
result = mid
left = mid + 1 # Continue right
elif arr[mid] < target:
left = mid + 1
else:
right = mid - 1
return result

# Find insertion position
def searchInsert(arr, target):
left, right = 0, len(arr) - 1
while left <= right:
mid = left + (right - left) // 2
if arr[mid] < target:
left = mid + 1
else:
right = mid - 1
return left # left points to insertion position

# Count occurrences
def countOccurrences(arr, target):
left = leftBound(arr, target)
if left == -1:
return 0
right = rightBound(arr, target)
return right - left + 1

# Test
arr = [1, 2, 2, 2, 3, 4, 5]
print(f"Search 2: {binarySearch(arr, 2)}")
print(f"Left bound 2: {leftBound(arr, 2)}")
print(f"Right bound 2: {rightBound(arr, 2)}")
print(f"Insert 2.5: {searchInsert(arr, 2.5)}")
print(f"Count 2: {countOccurrences(arr, 2)}")

Common Pitfalls

warning

Integer overflow in mid: (left + right) // 2 can overflow. Use left + (right - left) // 2 instead.

Loop condition confusion: left <= right for exact match; left < right for boundaries. Wrong choice causes infinite loops or missed answers.

Wrong return value: After loop, left points to insertion position for missing elements. right points to last checked position. Know which to return.

Forgetting to eliminate half: If mid logic doesn't properly set left or right, search doesn't narrow. Verify eliminating exactly half each iteration.

Boundary conditions: Empty arrays, single element arrays, target outside range all require explicit handling or correct loop logic.

Self-Check

  1. Trace binary search on [1,3,5,7] searching for 5. Show all mid values and boundary changes.
  2. Explain why left bound uses right = mid - 1 while searching continues. What's the invariant?
  3. After loop in standard search, what does left position represent?

One Takeaway

info

Binary search's power comes from consistent halving, not complex logic. Master template: left <= right with proper mid calculation and half elimination. Boundary searches extend template by continuing after finding target. Off-by-one errors plague binary search—use standard templates and trace examples to build confidence.

References

  • Cormen, T. H., Leiserson, C. E., Rivest, R. L., & Stein, C. (2009). Introduction to Algorithms (3rd ed.). MIT Press.
  • McDowell, G. L. (2015). Cracking the Coding Interview (6th ed.). CareerCup.

Search space reduction

  • Halving Search Space: Reduce search space by half each iteration
  • O(log n) Complexity: Logarithmic time complexity
  • Space Efficiency: Constant space complexity
  • Convergence: Guaranteed to find solution or determine absence

Boundary conditions

  • Left and Right Pointers: Managing search boundaries
  • Integer Overflow: Handling large numbers in midpoint calculation
  • Empty Array: Handling edge case of empty input
  • Single Element: Handling array with one element

Implementation variations

  • Recursive Implementation: Using recursion for binary search
  • Iterative Implementation: Using loops for binary search
  • Template Approach: Generic template for binary search problems
  • Custom Comparison: Using custom comparison functions

Search in rotated array

  • Rotated Sorted Array: Array rotated at unknown pivot
  • Find Pivot: Locate rotation point
  • Search in Rotated Array: Find target in rotated array
  • Minimum in Rotated Array: Find minimum element