diff --git a/dev/algorithm/Бинарный поиск.md b/dev/algorithm/Бинарный поиск.md new file mode 100644 index 00000000..6a3d82a0 --- /dev/null +++ b/dev/algorithm/Бинарный поиск.md @@ -0,0 +1,24 @@ +--- +aliases: +tags: + - maturity/🌱 +date: + - - 2024-04-07 +zero-link: + - "[[../../meta/zero/00 Алгоритм|00 Алгоритм]]" +parents: +linked: +link: https://struchkov.dev/blog/ru/java-binary-search/ +--- +Один их самых простых алгоритмов – это поиск элемента в отсортированном массиве. Это самая базовая алгоритмическая задача, которую нередко спрашивают на собеседованиях. + +С одной стороны, для подобных алгоритмов используют уже готовые функции стандартной библиотеки, с другой – подобные вопросы на собеседованиях позволяют узнать полезное о кандидате. + +Первое что приходи на ум: перебор элементов в массиве до нужного, тогда если количество элементов равно n и нужный нам элемент будет последним, нам потребуется сделать n проверок элементов до нахождения нужного, про такой случай и говорят что сложность алгоритма равна O(n). + +Рассмотрим другой подход - бинарный поиск – возьмем средний элемент отсортированного массива и сравним его c искомым. Если элемент меньше – продолжим поиск в левой части массива, если больше в правой, пока не останется нужный элемент. Таким образом нам понадобится число операций равное тому, сколько раз нам нужно поделить массив размером n пополам. + +Например, для массива в 16 элементов мы сначала поделим его на два по 8, потом 8 на два по 4, потом 4 на два по 2 и на конец 2 пополам, те всего 4 операции в худшем случае. Такое число равно двоичному логарифму. + +Реализации: +- [Бинарный поиск на Java](../java/Бинарный%20поиск%20на%20Java.md) \ No newline at end of file diff --git a/dev/java/Бинарный поиск на Java.md b/dev/java/Бинарный поиск на Java.md new file mode 100644 index 00000000..d7f35936 --- /dev/null +++ b/dev/java/Бинарный поиск на Java.md @@ -0,0 +1,84 @@ +--- +aliases: +tags: + - maturity/🌱 +date: + - - 2024-04-07 +zero-link: + - "[[../../meta/zero/00 Алгоритм|00 Алгоритм]]" + - "[[../../meta/zero/00 Снипеты для Java|00 Снипеты для Java]]" +parents: + - "[[../algorithm/Бинарный поиск|Бинарный поиск]]" +linked: +link: https://struchkov.dev/blog/ru/java-binary-search/ +--- +### Без рекурсии +```java +public class Binary { + + public static void main(String[] args) { + int[] values = {1, 1, 2, 3, 4, 10}; + int valueToFind = 3; + + System.out.printf("Index = %d%n", binarySearch(values, valueToFind, 0, values.length - 1)); + } + + private static int binarySearch(int[] sortedArray, int valueToFind, int low, int high) { + int index = -1; + + while (low <= high) { + int mid = low + (high - low) / 2; + if (sortedArray[mid] < valueToFind) { + low = mid + 1; + } else if (sortedArray[mid] > valueToFind) { + high = mid - 1; + } else if (sortedArray[mid] == valueToFind) { + index = mid; + break; + } + } + return index; + } + +} +``` + +### С использованием рекурсии +```java +public class Binary { + + public static void main(String[] args) { + int[] values = {1, 1, 2, 3, 4, 10}; + int valueToFind = 3; + + System.out.printf("Index = %d%n", binarySearch(values, valueToFind, 0, values.length - 1)); + } + + private static int binarySearch(int[] values, int valueToFind, int l, int r) { + if (l == r) { + return (values[l] == valueToFind) ? l : -1; + } + + int m = l + (r - l) / 2; + + if (valueToFind > values[m]) { + return binarySearch(values, valueToFind, m + 1, r); + } else if (values[m] > valueToFind) { + return binarySearch(values, valueToFind, l, m - 1); + } + return m; + } + +} +``` + +Если элемент не найден, то вернется `-1`. + +> [!WARNING] m = l + (r - l) / 2; +> Во многих примерах в интернете можно встретить запись `int m = (l + r) / 2;`, вместо `int mid = l + (r - l) / 2;`. И у меня в заметке тоже была такая запись, пока один из читателей не обратил на это внимание. +> +> Но использование второго варианта является лучшей практикой, так как это помогает избежать переполнения, когда размер массива велик. +> +> Например, если `l = 2147483647` и `r = 2147483647`, сумма `l` и `r` будет равна 4294967294, что превышает максимальное значение, которое может удерживать `int`, вызывая переполнение. +> +> С другой стороны, если вы используете `mid = l + (r - l) / 2;` это будет работать, как и ожидалось, потому что вычитание будет сделано первым, а результат будет равен нулю, поэтому деление будет равно нулю, а сложение вернет значение `l`. \ No newline at end of file diff --git a/meta/zero/00 Алгоритм.md b/meta/zero/00 Алгоритм.md new file mode 100644 index 00000000..5a4ed38d --- /dev/null +++ b/meta/zero/00 Алгоритм.md @@ -0,0 +1,8 @@ +--- +tags: + - type/zero-link +parents: + - "[[00 Разработка]]" +title: Алгоритм +--- +- [Бинарный поиск на Java](../../dev/java/Бинарный%20поиск%20на%20Java.md) \ No newline at end of file diff --git a/meta/zero/00 Снипеты для Java.md b/meta/zero/00 Снипеты для Java.md index d4fec63d..95c9e4d7 100644 --- a/meta/zero/00 Снипеты для Java.md +++ b/meta/zero/00 Снипеты для Java.md @@ -13,4 +13,5 @@ aliases: - [Mock конфигурация Oauth2 для SpringBoot](../../dev/snippet/Mock%20конфигурация%20Oauth2%20для%20SpringBoot.md) - [Несколько подключений к базе H2](../../dev/snippet/Несколько%20подключений%20к%20базе%20H2.md) - [Дебаг приложения на этапе компиляции IntelliJ IDEA](../../dev/snippet/Дебаг%20приложения%20на%20этапе%20компиляции%20IntelliJ%20IDEA.md) -- [Логирование SQL в Hibernate](../../dev/java/hibernate/Логирование%20SQL%20в%20Hibernate.md) \ No newline at end of file +- [Логирование SQL в Hibernate](../../dev/java/hibernate/Логирование%20SQL%20в%20Hibernate.md) +- [Бинарный поиск на Java](../../dev/java/Бинарный%20поиск%20на%20Java.md) \ No newline at end of file