11 апреля 2022
В задачах на применение классических алгоритмов часто используют бинарный (двоичный) поиск. Его можно применять только на предварительно отсортированном массиве. Самый простой алгоритм сортировки см. в статье Пузырьковая сортировка.
Суть бинарного поиска можно описать как «разделяй и властвуй». Исходный отсортированный по порядку массив мы делим пополам и проверяем элемент посередине. Если он равен тому, который мы ищем, то возвращаем его индекс. Если не равен, то проверяем границы и выбираем ту половину, в которой искомый элемент может находиться и выполняем проверку снова. Так мы сужаем область поиска до тех пор, пока левая граница не станет равна правой. Если элемент не удалось найти, возвращаем -1.
Рассмотрим реализацию на Java на примере массива целых чисел:
Поиск будет выполнен довольно быстро. В О-нотации сложность алгоритма равна O(log(N)). Тогда как если бы искали элемент прямым перебором, проверяя последовательно каждый элемент, то сложность была бы O(N), т.е. кратная количеству элементов.
Обобщённая реализация не сильно будет отличаться от исходной. Параметризуем метод binarySearch() типом T, реализующим стандартный интерфейс Comparable. На вход принимаем массив из элементов типа T. Искать будем также элемент типа T.
Ключевым отличием здесь является использование метода compareTo() из интерфейса Comparable. Результат его работы мы сравниваем с нулём:
Этот контракт легко запомнить, если в условии мысленно заменить compareResult и 0 на left и right соответственно.
Вы можете самостоятельно протестировать данную реализацию на пустом массиве, на массиве содержащем искомый элемент и на массиве его не содержащем.
А мы выполним следующий синтетический тест: сгенерим массив из миллиона элементов, где значение элемента равно его индексу, умноженному на 10. То есть он заведомо отсортирован по возрастанию. Элементы массива будут иметь тип BigInteger, реализующий интерфейс Comparable. Поищем средний элемент со значением 500 000.
Как видите, отличия в реализации простого и обобщённого метода минимальны.
Kotlin, Java, Spring, Spring Boot, Spring Data, SQL, PostgreSQL, Oracle, Linux, Hibernate, Collections, Stream API, многопоточность, файлы, Nginx, Apache, maven, gradle, JUnit, YouTube, новости, руководство, ООП, алгоритмы, головоломки, rest, GraphQL, Excel, XML, json, yaml.