Линейный поиск в Python: найти элемент перебором
Автор: Казачкин Даниил Михайлович · Обновлено
Линейный поиск сравнивает цель с элементами по порядку. Он работает для несортированного списка и может остановиться на первом совпадении. Если нужен индекс, удобно перебирать enumerate; при отсутствии результата используют явный маркер.
Возвращаем позицию или -1
def find_index(values, target):
for index, value in enumerate(values):
if value == target:
return index
return -1
print(find_index([8, 3, 5, 3], 3))
print(find_index([8, 3, 5, 3], 7))Ожидаемый вывод:
1
-1Первый return завершает функцию на первом совпадении. Финальный return выполняется только после полного прохода без результата.
Маркер не должен совпадать с индексом
Индексы списка не бывают -1 в смысле результата поиска, хотя Python использует -1 для доступа к последнему элементу. Поэтому вызывающий код должен проверить marker до обращения values[index], иначе отсутствие ошибочно превратится в последний элемент. Альтернатива — вернуть None.
Типичная ошибка — разместить return -1 внутри цикла: тогда функция проверит только первый элемент. Ещё одна ошибка — сравнивать index с target вместо value. Трассировка пар index, value быстро показывает проблему.
Поиск по условию
Измените функцию так, чтобы она возвращала индекс первого отрицательного числа. Проверьте [4, 0, -2, -5] → 2, список без отрицательных и список, где отрицательный элемент первый. Затем напишите вариант, собирающий все индексы цели в список. Для [3, 1, 3, 3] и цели 3 ожидаются [0, 2, 3]. Объясните, почему в этом варианте нельзя завершаться на первом совпадении.
Первое или все совпадения
Сформулируйте три разных API поиска: вернуть первый индекс, все индексы или логический факт наличия. Реализуйте каждый и проверьте на списке с повторами, пустом списке и отсутствии цели. Сравните ранний return с полным проходом и не используйте один маркер там, где вызывающий код ожидает другой. Затем добавьте параметр start, определяющий начальную позицию, и проверьте его диапазон. Упражнение показывает, что «найти элемент» недостаточно для контракта функции: нужно определить форму результата, поведение при повторах и отсутствие значения.
Практикум: контракт линейного поиска
Реализуйте три варианта: первый индекс цели, все индексы и логический факт наличия. Проверьте список с повторами, отсутствие, пустой список и цель в конце. Для первого индекса используйте ранний return, а сообщение об отсутствии размещайте после полного цикла. Сравните маркеры -1 и None и выберите один контракт. Добавьте параметр start, проверьте его границы и не позволяйте отрицательному значению случайно менять смысл без документации.
Контрольная точка
Почему return -1 внутри цикла после первого несовпадения неверен? Один элемент ничего не говорит об оставшейся части; нужен тест, где цель стоит второй.
Частые вопросы
Чем оператор in отличается от ручного поиска?
in отвечает только на вопрос наличия и обычно выполняет линейную проверку для списка. Ручная функция нужна для индекса, всех совпадений, особого критерия или изучения алгоритма.
Связанные исследования
- Алгоритм Гровера: квантовый поиск, оракул и небольшой пример на Qiskit — Объясняем алгоритм Гровера: O(√N) запросов, фазовый оракул, амплитудное усиление, пример Qiskit и ограничения реального ускорения.