← Назад к вопросам

Приведи пример алгоритма поиска

2.0 Middle🔥 121 комментариев
#Коллекции и структуры данных

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI6 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Конечно, приведу подробный пример и разбор одного из фундаментальных алгоритмов поиска — бинарного поиска (Binary Search). Это идеальный пример для собеседования, так как он демонстрирует понимание алгоритмической эффективности, работу с массивами и логику «разделяй и властвуй».

Бинарный поиск (Binary Search)

Это алгоритм для поиска элемента в отсортированном массиве. Его ключевая идея — на каждом шаге делить интервал поиска пополам, отбрасывая ту половину, где искомый элемент заведомо находиться не может.

Принцип работы

Алгоритм работает только с отсортированными данными (по возрастанию или убыванию). Основные шаги:

  • Инициализируем два указателя: low (начало массива, индекс 0) и high (конец массива, индекс n-1).
  • Находим средний индекс mid между low и high.
  • Сравниваем элемент в позиции mid с искомым значением (target).
  • Если они равны — поиск успешен, возвращаем mid.
  • Если target больше элемента в mid, то отбрасываем левую половину (включая mid), сдвигая low на mid + 1.
  • Если target меньше элемента в mid, то отбрасываем правую половину (включая mid), сдвигая high на mid - 1.
  • Повторяем шаги, пока low не станет больше high. Если элемент не найден, возвращаем -1.

Ключевые характеристики

  • Сложность по времени: O(log n). Это экспоненциально быстрее линейного поиска (O(n)) на больших массивах. Каждый шаг уменьшает пространство поиска вдвое.
  • Сложность по памяти: O(1). Алгоритм использует только постоянное количество дополнительной памяти для переменных-указателей.
  • Обязательное условие: Отсортированный массив.

Пример реализации на Swift

Вот две реализации: итеративная (циклическая) и рекурсивная. На собеседовании часто просят написать итеративную версию.

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

func binarySearch<T: Comparable>(_ array: [T], _ target: T) -> Int? {
    var low = 0
    var high = array.count - 1

    while low <= high {
        let mid = (low + high) / 2 // Или low + (high - low) / 2 для избежания переполнения
        let guess = array[mid]

        if guess == target {
            return mid // Элемент найден, возвращаем индекс
        } else if guess < target {
            low = mid + 1 // Искомый элемент в правой половине
        } else {
            high = mid - 1 // Искомый элемент в левой половине
        }
    }
    return nil // Элемент не найден
}

// Пример использования
let sortedArray = [1, Chitat'3, 5, 7, 9, 11, 13, 15, 17, 19]
if let index = binarySearch(sortedArray, 11) {
    print("Элемент найден по индексу: \(index)") // Напечатает: Элемент найден по индексу: 5
} else {
    print("Элемент не найден")
}

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

func binarySearchRecursive<T: Comparable>(_ array: [T], _ target: T, range: Range<Int>) -> Int? {
    guard range.lowerBound < range.upperBound else {
        return nil // Базовый случай: диапазон пуст
    }

    let midIndex = range.lowerBound + (range.upperBound - range.lowerBound) / 2
    let midValue = array[midIndex]

    if midValue == target {
        return midIndex
    } else if midValue < target {
        // Ищем в правой половине
        return binarySearchRecursive(array, target, range: midIndex + 1..<range.upperBound)
    } else {
        // Ищем в левой половине
        return binarySearchRecursive(array, target, range: range.lowerBound..<midIndex)
    }
}

// Пример использования
let index = binarySearchRecursive(sortedArray, 7, range: 0..<sortedArray.count) // Вернет 3

Типичные вопросы на собеседовании по бинарному поиску

  1. «Почему сложность O(log n)?» Потому что на каждом шаге количество элементов для проверки уменьшается в 2 раза. Максимальное число шагов — это логарифм от n по основанию 2.
  2. «Что будет, если массив не отсортирован?» Алгоритм даст неправильный результат, так как принцип отбрасывания половины основан на гарантии порядка элементов.
  3. «Как избежать переполнения при вычислении mid Использовать формулу mid = low + (high - low) / 2 вместо (low + high) / 2. Это важно для очень больших массивов, где сумма low + high может превысить Int.max.
  4. «Модификации алгоритма»: Могут спросить о вариантах поиска:
    *   **Первое или последнее вхождение** в массиве с дубликатами.
    *   **Поиск в «сдвинутом» (rotated) отсортированном массиве**.
    *   **Поиск ближайшего элемента**, если точного совпадения нет.

Сравнение с другими алгоритмами поиска

  • Линейный поиск (Linear Search): O(n). Проверяет элементы последовательно. Универсален, работает с любыми данными, но медленен на больших объемах.
  • Поиск в хеш-таблице (Hash Table Lookup): O(1) в среднем. Самый быстрый, но требует дополнительной памяти и не поддерживает порядок или быстрый поиск по диапазону.

Вывод: Бинарный поиск — это классический, эффективный и элегантный алгоритм, который является основой для решения более сложных задач (например, поиск в структурах данных вроде Set или Dictionary в Swift, которые внутри используют хеш-таблицы или деревья, также основанные на принципе деления пополам). Умение его реализовать и объяснить демонстрирует сильные фундаментальные знания кандидата.

Приведи пример алгоритма поиска | PrepBro