Как работает бинарный поиск?
- Какая сложность у бинарного поиска?
- Как найти первое вхождение элемента в отсортированном массиве?
- Что такое бинарный поиск по ответу?
В отсортированном массиве сравниваем искомое с серединой и отбрасываем половину, где его быть не может: 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 минут бесплатно.