Бинарный поиск

Бинарный поиск (Binary Search): итеративная и рекурсивная реализации, пошаговый разбор, код на Python, сложность O(log n) и требования к данным.

Бинарный поиск работает только на отсортированном массиве. На каждом шаге он сравнивает цель со средним элементом и отбрасывает половину оставшегося диапазона. Это позволяет находить элемент за O(log n) шагов.

Сложность: O(log n); O(1) памяти для итеративного варианта, O(log n) для рекурсивного.

Идея алгоритма

Вспомни игру «угадай число от 1 до 100». Умный игрок называет 50. Если загадано 72 — он называет 75, затем 62, 68, 71, 72. За 7 вопросов — любое число от 1 до 100. Это и есть бинарный поиск: каждый вопрос вдвое сужает диапазон.

Пошаговый разбор

Отсортированный массив [2, 5, 8, 12, 16, 23, 38, 56, 72, 91], ищем 23:

Шаг

low

high

mid

arr[mid]

Действие

1

0

9

4

16

16 < 23 → low = 5

2

5

9

7

56

56 > 23 → high = 6

3

5

6

5

23

Найден! → возврат 5

За 3 шага вместо 6 при линейном поиске. При 10 000 элементов бинарный поиск возьмёт не более 14 шагов.

Итеративная реализация

def binary_search(arr, target):
    low, high = 0, len(arr) - 1
    while low <= high:
        mid = (low + high) // 2
        if arr[mid] == target:
            return mid
        elif arr[mid] < target:
            low = mid + 1       # цель правее
        else:
            high = mid - 1      # цель левее
    return -1                   # не найден

arr = [2, 5, 8, 12, 16, 23, 38, 56, 72, 91]
print(binary_search(arr, 23))   # 5
print(binary_search(arr, 10))   # -1

Вывод:

5
-1

Рекурсивная реализация

def binary_search_rec(arr, target, low=0, high=None):
    if high is None:
        high = len(arr) - 1
    if low > high:
        return -1
    mid = (low + high) // 2
    if arr[mid] == target:
        return mid
    elif arr[mid] < target:
        return binary_search_rec(arr, target, mid + 1, high)
    else:
        return binary_search_rec(arr, target, low, mid - 1)

arr = [2, 5, 8, 12, 16, 23, 38, 56, 72, 91]
print(binary_search_rec(arr, 56))   # 7
print(binary_search_rec(arr, 1))    # -1

Вывод:

7
-1

Сложность и свойства

Вариант

Случай

Время

Память

Итеративный

Лучший (середина)

O(1)

O(1)

Итеративный

Средний/Худший

O(log n)

O(1)

Рекурсивный

Средний/Худший

O(log n)

O(log n) стек

Обязательное условие: массив должен быть отсортирован. Если данные поступают динамически — поддерживать их в упорядоченном виде помогают сбалансированные деревья (BST, AVL) или структура bisect в Python.

Когда применять

  • Данные отсортированы и поиск выполняется многократно.
  • Нужен быстрый ответ «есть ли элемент» в большом наборе данных.
  • Поиск границы вставки (lower_bound / upper_bound) — стандартная задача в конкурентном программировании.

В Python стандартная библиотека предоставляет готовый бинарный поиск: import bisect; bisect.bisect_left(arr, target).

Коротко

  • Бинарный поиск делит диапазон пополам на каждом шаге — только на отсортированных данных.
  • O(log n) шагов: при n=1 000 000 хватит 20 сравнений.
  • Итеративный вариант: O(1) памяти; рекурсивный: O(log n) стек.
  • В Python — bisect, в Java — Arrays.binarySearch.
Проверьте себя
1. Какое главное требование для применения бинарного поиска?
AМассив должен содержать только числа
BМассив должен быть отсортирован
CМассив должен иметь чётный размер
DЭлемент должен быть уникальным
2. Сколько шагов потребует бинарный поиск в массиве из 1 024 элементов?
A1 024
B512
CНе более 10
DНе более 32
3. Как рассчитывается средний индекс mid?
Amid = low + high
Bmid = (low + high) // 2
Cmid = high - low
Dmid = low * high
4. Чем отличается рекурсивный бинарный поиск от итеративного?
AРекурсивный быстрее
BРекурсивный требует O(log n) стека вместо O(1)
CИтеративный не работает на больших массивах
DИтеративный не находит элементы в начале массива
Поддержать проект