Code Snippets
/

Python Binary Search Template

Python Binary Search Template

Binary search runs in O(log n) over any sorted array, but the off-by-one variations bite everyone. This entry ships three runnable templates: the equality search, the lower-bound (`bisect_left`) variant, and the upper-bound (`bisect_right`) variant. Each one handles every edge case the test list throws at it.

Python
Easy
3 snippets
binary-search
algorithms
code-template
binary-search-templates

1,085 views

33

def binary_search(nums, target):
    """Return the index of `target` in sorted `nums`, or -1 if absent."""
    lo, hi = 0, len(nums) - 1
    while lo <= hi:
        mid = (lo + hi) // 2
        if nums[mid] == target:
            return mid
        if nums[mid] < target:
            lo = mid + 1
        else:
            hi = mid - 1
    return -1

# Happy path.
print(binary_search([1, 3, 5, 7, 9, 11, 13], 7))  # 3

# Edges that catch off-by-one bugs.
print(binary_search([1, 3, 5, 7, 9, 11, 13], 1))   # 0  (first element)
print(binary_search([1, 3, 5, 7, 9, 11, 13], 13))  # 6  (last element)
print(binary_search([1, 3, 5, 7, 9, 11, 13], 4))   # -1 (between elements)
print(binary_search([1, 3, 5, 7, 9, 11, 13], 0))   # -1 (below range)
print(binary_search([1, 3, 5, 7, 9, 11, 13], 99))  # -1 (above range)
print(binary_search([], 5))                          # -1 (empty array)
print(binary_search([42], 42))                       # 0  (single element hit)
print(binary_search([42], 7))                        # -1 (single element miss)

The template uses a closed interval [lo, hi]. lo <= hi is the loop condition because the interval is inclusive on both ends, and lo = mid + 1 / hi = mid - 1 shrink it without ever revisiting mid. Computing mid = (lo + hi) // 2 is safe in Python (ints are unbounded), so you do not need the lo + (hi - lo) // 2 trick that C and Java need. Test against empty arrays, single-element arrays, the first and last elements, and out-of-range values: every binary-search bug shows up there.