Вопрос с собеседования · Основы

Как работает бинарный поиск?

JuniorПоиск
Ещё спрашивают так:
  • Какая сложность у бинарного поиска?
  • Как найти первое вхождение элемента в отсортированном массиве?
  • Что такое бинарный поиск по ответу?
Коротко

В отсортированном массиве сравниваем искомое с серединой и отбрасываем половину, где его быть не может: O(log n) шагов.

  • Миллион элементов — не больше 20 сравнений, миллиард — 30
  • Типичные ошибки: границы, бесконечный цикл, переполнение (lo + hi) / 2 в языках с фиксированными целыми

А ещё Обобщение — поиск по ответу: на монотонной функции найти первую точку, где условие стало истинным

Попробуйте сами

Бинарный поиск против линейного

Подробно

Условие — данные упорядочены. Держим границы lo и hi, внутри которых может быть искомое. Смотрим на средний элемент:

  • равен искомому — нашли;
  • меньше — искомое правее, lo = mid + 1;
  • больше — левее, hi = mid - 1.

Каждый шаг уменьшает область вдвое, поэтому шагов не больше log₂ n + 1. Для сравнения: линейный поиск в худшем случае смотрит все n элементов.

Частые ошибки:

  • неверные границы и условие цикла (< против <=), из-за чего пропускается последний элемент или цикл не заканчивается;
  • в языках с переполнением целых — (lo + hi) / 2 может переполниться; безопасно lo + (hi - lo) / 2;
  • поиск в неотсортированных данных.

Варианты: найти первое или последнее вхождение (lower bound / upper bound — не останавливаться при равенстве, а сдвигать границу), найти место вставки (bisect в Python). Поиск по ответу — когда есть монотонное условие: «минимальная пропускная способность, при которой всё успеем», «первая сломанная версия» (git bisect).

Пример

def lower_bound(a, target):
    """Первый индекс i, где a[i] >= target (или len(a))."""
    lo, hi = 0, len(a)
    while lo < hi:
        mid = (lo + hi) // 2
        if a[mid] < target:
            lo = mid + 1
        else:
            hi = mid
    return lo

a = [1, 3, 3, 3, 7, 9]
lower_bound(a, 3)   # 1 — первое вхождение
lower_bound(a, 4)   # 4 — место вставки

Что хотят услышать

  • Условие отсортированности и идея деления пополам.
  • Сложность O(log n) и интуиция, сколько это шагов.
  • Рабочий код без ошибок в границах.
  • Варианты: первое вхождение, поиск по ответу — плюс.

Частые ошибки

  • Бесконечный цикл из-за lo = mid при lo < hi с округлением вниз.
  • Применять к неотсортированным данным.

Проверьте себя

Один верный вариант. Подумайте, потом откройте ответ.

Показать варианты и ответ
  • ✗Работает на любом массиве, сортировка не нужна
  • ✗Перебирает элементы с двух концов одновременно, поэтому для миллиона элементов нужно около 500 000 сравнений
  • ✓В отсортированном массиве сравнивает с серединой и отбрасывает половину — O(log n)
  • ✗Выражение (lo + hi) / 2 безопасно в любом языке

Что спросят дальше

Связанные вопросы

Партнёр платформы

Разбор собеседования с sotto

После собеседования sotto разбирает разговор: оценка, каждый вопрос — хорошо, частично или слабо, чего не хватило в ответе и над чем поработать к следующему разу. Первые 30 минут бесплатно.

Разбор собеседования