Инструменты пользователя

Инструменты сайта


basics_of_algorithms:binary_search

Различия

Здесь показаны различия между двумя версиями данной страницы.

Ссылка на это сравнение

Предыдущая версия справа и слева Предыдущая версия
Следующая версия
Предыдущая версия
basics_of_algorithms:binary_search [2023/10/03 19:21]
werwolf [Как ускорить алгоритм перебора]
basics_of_algorithms:binary_search [2023/10/03 19:43] (текущий)
werwolf [Как реализовать бинарный поиск]
Строка 109: Строка 109:
 </​code>​ </​code>​
 </​details>​ </​details>​
-PHP 
  
-<​code>​+ 
 + 
 +<​details>​ 
 +<​summary>​PHP</​summary>​ 
 +<​code ​php>
 <?php <?php
  
Строка 127: Строка 130:
 } }
 </​code>​ </​code>​
 +</​details>​
  
-Java +<​details>​ 
- +<​summary>​Java</​summary>​ 
-<​code>​+<​code ​java>
 class App { class App {
  
Строка 148: Строка 152:
 } }
 </​code>​ </​code>​
 +</​details>​
  
 Функция ''​isStopWord()''​ перебирает **слова-кандидаты**,​ последовательно сравнивает их с каждой строкой в массиве стоп-слов и возвращает ''​true''​ или ''​false''​. Мы вставили сюда слова из нашей таблицы,​ но, чтобы код не получился слишком большим,​ ограничились десятком слов. Функция ''​isStopWord()''​ перебирает **слова-кандидаты**,​ последовательно сравнивает их с каждой строкой в массиве стоп-слов и возвращает ''​true''​ или ''​false''​. Мы вставили сюда слова из нашей таблицы,​ но, чтобы код не получился слишком большим,​ ограничились десятком слов.
Строка 202: Строка 207:
 Вот функция,​ которая проверяет,​ есть ли стоп-слово в отсортированном массиве:​ Вот функция,​ которая проверяет,​ есть ли стоп-слово в отсортированном массиве:​
  
-<​code>​+<​code ​javascript>
 const stopWords = ['​а',​ '​без',​ '​ближе',​ '​браво',​ '​бы',​ '​вам',​ '​вас',​ '​весь',​ '​во',​ '​все',​ '​всего',​ '​вы'​];​ const stopWords = ['​а',​ '​без',​ '​ближе',​ '​браво',​ '​бы',​ '​вам',​ '​вас',​ '​весь',​ '​во',​ '​все',​ '​всего',​ '​вы'​];​
  
Строка 234: Строка 239:
 </​code>​ </​code>​
  
-Python 
  
-<​code>​+<​details>​ 
 +<​summary>​Python</​summary>​ 
 +<​code ​python>
 stop_words = ['​а',​ '​без',​ '​ближе',​ '​браво',​ '​бы',​ '​вам',​ '​вас',​ '​весь',​ '​во',​ '​все',​ '​всего',​ '​вы'​] stop_words = ['​а',​ '​без',​ '​ближе',​ '​браво',​ '​бы',​ '​вам',​ '​вас',​ '​весь',​ '​во',​ '​все',​ '​всего',​ '​вы'​]
  
Строка 262: Строка 268:
     return False     return False
 </​code>​ </​code>​
 +</​details>​
  
-PHP +<​details>​ 
- +<​summary>​PHP</​summary>​ 
-<​code>​+<​code ​php>
 <?php <?php
  
Строка 292: Строка 299:
 }; };
 </​code>​ </​code>​
 +</​details>​
  
-Java +<​details>​ 
- +<​summary>​Java</​summary>​ 
-<​code>​+<​code ​java>
 class App { class App {
  
Строка 331: Строка 339:
 } }
 </​code>​ </​code>​
 +</​details>​
  
-https://​replit.com/​@hexlet/​algorithms-binary-search 
- 
-https://​replit.com/​@hexlet/​binarysearch 
  
 Разберемся,​ как эта функция работает. На каждом шаге алгоритма мы взаимодействуем с областью поиска. Чтобы определить ее, нам достаточно хранить индексы его первого и последнего элементов. В самом начале область поиска совпадает со всем массивом. Разберемся,​ как эта функция работает. На каждом шаге алгоритма мы взаимодействуем с областью поиска. Чтобы определить ее, нам достаточно хранить индексы его первого и последнего элементов. В самом начале область поиска совпадает со всем массивом.
  
-<​code>​+<​code ​javascript>
 // индекс первого элемента области поиска // индекс первого элемента области поиска
 let first = 0; let first = 0;
Строка 345: Строка 351:
 </​code>​ </​code>​
  
-Python 
  
-<​code>​+<​details>​ 
 +<​summary>​Python</​summary>​ 
 +<​code ​python>
 # индекс первого элемента области поиска # индекс первого элемента области поиска
 first = 0 first = 0
Строка 353: Строка 360:
 last = len(stop_words) - 1 last = len(stop_words) - 1
 </​code>​ </​code>​
 +</​details>​
  
-PHP +<​details>​ 
- +<​summary>​PHP</​summary>​ 
-<​code>​+<​code ​php>
 <?php <?php
  
Строка 362: Строка 370:
 $last = count(stopWords) - 1; $last = count(stopWords) - 1;
 </​code>​ </​code>​
 +</​details>​
  
-Java 
  
-<​code>​+<​details>​ 
 +<​summary>​Java</​summary>​ 
 +<​code ​java>
 // индекс первого элемента области поиска // индекс первого элемента области поиска
 var first = 0; var first = 0;
Строка 371: Строка 381:
 var last = stopWords.size() - 1; var last = stopWords.size() - 1;
 </​code>​ </​code>​
 +</​details>​
  
 Элементы в массивах JavaScript нумеруются с нуля, поэтому сначала индекс первого элемента равен 0, а индекс последнего — на единицу меньше длины массива. Чтобы убедиться в этом, представьте массив,​ например,​ из четырех элементов:​ его элементы будут иметь индексы 0, 1, 2 и 3. Элементы в массивах JavaScript нумеруются с нуля, поэтому сначала индекс первого элемента равен 0, а индекс последнего — на единицу меньше длины массива. Чтобы убедиться в этом, представьте массив,​ например,​ из четырех элементов:​ его элементы будут иметь индексы 0, 1, 2 и 3.
Строка 376: Строка 387:
 На каждом шаге мы сравниваем слово-кандидат со словом из середины области. Найти среднее слово несложно:​ его индекс находится посередине между первым и последним словом. На каждом шаге мы сравниваем слово-кандидат со словом из середины области. Найти среднее слово несложно:​ его индекс находится посередине между первым и последним словом.
  
-<​code>​+<​code ​javascript>
 const middle = (first + last) / 2; const middle = (first + last) / 2;
 </​code>​ </​code>​
  
-Python 
  
-<​code>​+<​details>​ 
 +<​summary>​Python</​summary>​ 
 +<​code ​python>
 middle = (first + last) / 2 middle = (first + last) / 2
 </​code>​ </​code>​
 +</​details>​
  
-PHP +<​details>​ 
- +<​summary>​PHP</​summary>​ 
-<​code>​+<​code ​php>
 <?php <?php
  
 $middle = ($first + $last) / 2 $middle = ($first + $last) / 2
 </​code>​ </​code>​
 +</​details>​
  
-Java +<​details>​ 
- +<​summary>​Java</​summary>​ 
-<​code>​+<​code ​java>
 var middle = (first + last) / 2; var middle = (first + last) / 2;
 </​code>​ </​code>​
 +</​details>​
  
 В массиве с нечетным количеством элементов все просто:​ у нас есть центральный элемент и две равные половины слева и справа от него. В массиве с четным количеством элементов,​ длина левой и правой половин будет отличаться на единицу. В массиве с нечетным количеством элементов все просто:​ у нас есть центральный элемент и две равные половины слева и справа от него. В массиве с четным количеством элементов,​ длина левой и правой половин будет отличаться на единицу.
Строка 406: Строка 421:
 Чтобы справиться с этой ситуацией,​ мы округлим это значение вверх или вниз. Если вниз — левая половина будет на один элемент короче правой,​ а если вверх — наоборот. Можно выбрать любой вариант,​ алгоритм будет работать в обоих случаях. Округлим значение в меньшую сторону:​ Чтобы справиться с этой ситуацией,​ мы округлим это значение вверх или вниз. Если вниз — левая половина будет на один элемент короче правой,​ а если вверх — наоборот. Можно выбрать любой вариант,​ алгоритм будет работать в обоих случаях. Округлим значение в меньшую сторону:​
  
-<​code>​+<​code ​javascript>
 // индекс среднего элемента области поиска // индекс среднего элемента области поиска
 const middle = Math.floor((first + last) / 2); const middle = Math.floor((first + last) / 2);
 </​code>​ </​code>​
  
-Python +<​details>​ 
- +<​summary>​Python</​summary>​ 
-<​code>​+<​code ​python>
 middle = (first + last) // 2 middle = (first + last) // 2
 </​code>​ </​code>​
 +</​details>​
  
-PHP +<​details>​ 
- +<​summary>​PHP</​summary>​ 
-<​code>​+<​code ​php>
 $middle = round(($first + $last) / 2); $middle = round(($first + $last) / 2);
 </​code>​ </​code>​
 +</​details>​
  
-Java +<​details>​ 
- +<​summary>​Java</​summary>​ 
-<​code>​+<​code ​java>
 // В Java для целых чисел используется целочисленное деление // В Java для целых чисел используется целочисленное деление
 var middle = (first + last) / 2; var middle = (first + last) / 2;
 </​code>​ </​code>​
 +</​details>​
  
 Дальше есть три варианта развития событий. Дальше есть три варианта развития событий.
Строка 436: Строка 454:
 **Вариант 2:** Слово-кандидат может быть меньше слова из середины. Тогда надо отбросить все элементы справа и продолжать поиск только в левой части. На следующем шаге первое слово останется прежним,​ а последнее изменится. Последним словом в новой области поиска станет центральное слово из старой:​ **Вариант 2:** Слово-кандидат может быть меньше слова из середины. Тогда надо отбросить все элементы справа и продолжать поиск только в левой части. На следующем шаге первое слово останется прежним,​ а последнее изменится. Последним словом в новой области поиска станет центральное слово из старой:​
  
-<​code>​+<​code ​javascript>
 last = middle; last = middle;
 </​code>​ </​code>​
  
-Python +<​details>​ 
- +<​summary>​Python</​summary>​ 
-<​code>​+<​code ​python>
 last = middle last = middle
 </​code>​ </​code>​
 +</​details>​
  
-PHP +<​details>​ 
- +<​summary>​PHP</​summary>​ 
-<​code>​+<​code ​php>
 <?php <?php
  
 $last = $middle; $last = $middle;
 </​code>​ </​code>​
 +</​details>​
  
-Java +<​details>​ 
- +<​summary>​Java</​summary>​ 
-<​code>​+<​code ​java>
 last = middle; last = middle;
 </​code>​ </​code>​
 +<​details>​
  
-На самом деле мы можем не включать центральное слово в новую область. При проверке первого варианта мы убедились,​ что слово-кандидат с ним не совпадает. Новым последним словом будет то, которое находится слева от центрального:​+На самом деле мы можем не включать центральное слово в новую область. При проверке первого варианта мы убедились,​ что слово-кандидат с ним не совпадает. Новым последним словом будет то, которое находится слева от центрального: ​
  
-<​code>​+<​code ​javascript>
 last = middle - 1; last = middle - 1;
 </​code>​ </​code>​
  
-Python +<​details>​ 
- +<​summary>​Python</​summary>​ 
-<​code>​+<​code ​python>
 last = middle - 1 last = middle - 1
 </​code>​ </​code>​
 +</​details>​
  
-PHP +<​details>​ 
- +<​summary>​PHP</​summary>​ 
-<​code>​+<​code ​php>
 <?php <?php
  
 $last = $middle - 1; $last = $middle - 1;
 </​code>​ </​code>​
 +<​details>​
  
-Java +<​details>​ 
- +<​summary>​Java</​summary>​ 
-<​code>​+<​code ​java>
 last = middle - 1; last = middle - 1;
 </​code>​ </​code>​
 +</​details>​
  
 **Вариант 3:** Слово-кандидат может быть больше центрального слова. Тогда вместо правой границы надо двигать левую. Код окажется очень похожим:​ **Вариант 3:** Слово-кандидат может быть больше центрального слова. Тогда вместо правой границы надо двигать левую. Код окажется очень похожим:​
  
-<​code>​+<​code ​javascript>
 first = middle + 1; first = middle + 1;
 </​code>​ </​code>​
  
-Python+<​details>​ 
 +<​summary>​Python</​summary>​
  
-<​code>​+<​code ​python>
 first = middle + 1 first = middle + 1
 </​code>​ </​code>​
 +</​details>​
  
-PHP +<​details>​ 
 +<​summary>​PHP</​summary>​
 <​code>​ <​code>​
 <?php <?php
Строка 505: Строка 531:
 $first = $middle + 1; $first = $middle + 1;
 </​code>​ </​code>​
 +</​details>​
  
-Java +<​details>​ 
- +<​summary>​Java</​summary>​ 
-<​code>​+<​code ​java>
 first = middle + 1; first = middle + 1;
 </​code>​ </​code>​
 +</​details>​
  
 Мы сократили область поиска вдвое, а теперь надо повторить предыдущие шаги — тогда в нашей программе появится цикл: Мы сократили область поиска вдвое, а теперь надо повторить предыдущие шаги — тогда в нашей программе появится цикл:
  
-<​code>​+<​code ​javascript>
 while (???) { while (???) {
   // индекс среднего элемента области поиска   // индекс среднего элемента области поиска
Строка 534: Строка 562:
 </​code>​ </​code>​
  
-Python 
  
-<​code>​+<​details>​ 
 +<​summary>​Python</​summary>​ 
 +<​code ​python>
 while (???): while (???):
     # индекс среднего элемента области поиска     # индекс среднего элемента области поиска
Строка 552: Строка 581:
         first = middle + 1         first = middle + 1
 </​code>​ </​code>​
 +</​details>​
  
-PHP +<​details>​ 
- +<​summary>​PHP</​summary>​ 
-<​code>​+<​code ​php>
 <?php <?php
  
Строка 576: Строка 606:
 } }
 </​code>​ </​code>​
 +</​details>​
  
-Java+<​details>​ 
 +<​summary>​Java</​summary>​
  
-<​code>​+<​code ​java>
 while (???) { while (???) {
     // индекс среднего элемента области поиска     // индекс среднего элемента области поиска
Строка 598: Строка 630:
     }     }
 </​code>​ </​code>​
 +</​details>​
  
 Мы пока не знаем условия завершения цикла, поэтому написали три знака вопроса. Чтобы разобраться с условием,​ обратим внимание,​ что на каждом шаге первое и последнее слово двигаются к друг другу и когда-нибудь они совпадут. Тогда условие ''​first === last''​ станет истинным. Мы пока не знаем условия завершения цикла, поэтому написали три знака вопроса. Чтобы разобраться с условием,​ обратим внимание,​ что на каждом шаге первое и последнее слово двигаются к друг другу и когда-нибудь они совпадут. Тогда условие ''​first === last''​ станет истинным.
Строка 610: Строка 643:
 Слово-кандидат либо будет совпадать с центральным словом,​ либо нет. Если оно окажется меньше,​ у нас выполнится ветка: Слово-кандидат либо будет совпадать с центральным словом,​ либо нет. Если оно окажется меньше,​ у нас выполнится ветка:
  
-<​code>​+<​code ​javasript>
 last = middle - 1; last = middle - 1;
 </​code>​ </​code>​
  
-Python +<​details>​ 
- +<​summary>​Python</​summary>​ 
-<​code>​+<​code ​python>
 last = middle - 1 last = middle - 1
 </​code>​ </​code>​
 +</​details>​
  
-PHP+<​details>​ 
 +<​summary>​PHP</​summary>​
  
-<​code>​+<​code ​php>
 <?php <?php
  
 $last = $middle - 1; $last = $middle - 1;
 </​code>​ </​code>​
 +</​details>​
  
-Java+<​details>​ 
 +<​summary>​Java</​summary>​
  
-<​code>​+<​code ​java>
 last = middle - 1; last = middle - 1;
 </​code>​ </​code>​
 +</​details>​
  
 Мы помним,​ что значения ''​first'',​ ''​last''​ и ''​middle''​ совпадают,​ так что новое значение ''​last''​ окажется на единицу меньше ''​first''​. Ситуация кажется странной — как последнее слово может находиться перед первым?​ Мы помним,​ что значения ''​first'',​ ''​last''​ и ''​middle''​ совпадают,​ так что новое значение ''​last''​ окажется на единицу меньше ''​first''​. Ситуация кажется странной — как последнее слово может находиться перед первым?​
Строка 640: Строка 678:
 Такая же ситуация возникнет,​ если слово-кандидат будет больше среднего слова, но там сработает вторая ветка: Такая же ситуация возникнет,​ если слово-кандидат будет больше среднего слова, но там сработает вторая ветка:
  
-<​code>​+<​code ​javascript>
 first = middle + 1; first = middle + 1;
 </​code>​ </​code>​
  
-Python 
  
-<​code>​+<​details>​ 
 +<​summary>​Python</​summary>​ 
 + 
 +<​code ​python>
 first = middle + 1 first = middle + 1
 </​code>​ </​code>​
 +</​details>​
  
-PHP+<​details>​ 
 +<​summary>​PHP</​summary>​
  
-<​code>​+<​code ​php>
 <?php <?php
  
 $first = $middle + 1; $first = $middle + 1;
 </​code>​ </​code>​
 +</​details>​
  
-Java+<​details>​ 
 +<​summary>​Java</​summary>​
  
-<​code>​+<​code ​java>
 first = middle + 1; first = middle + 1;
 </​code>​ </​code>​
 +</​details>​
  
 Цикл следует остановить,​ когда левая граница станет больше правой. Но в операторе ''​while''​ мы записываем не условие остановки цикла, а условие продолжения,​ поэтому условие надо поменять на обратное:​ ''​first <= last''​. Если цикл завершается и кандидат в списке не найден,​ значит,​ поиск завершился неудачно — алгоритм вернет ''​false'':​ Цикл следует остановить,​ когда левая граница станет больше правой. Но в операторе ''​while''​ мы записываем не условие остановки цикла, а условие продолжения,​ поэтому условие надо поменять на обратное:​ ''​first <= last''​. Если цикл завершается и кандидат в списке не найден,​ значит,​ поиск завершился неудачно — алгоритм вернет ''​false'':​
  
-<​code>​+<​code ​javascript
 // пока область поиска не пуста // пока область поиска не пуста
 while (first <= last) { while (first <= last) {
Строка 675: Строка 720:
 </​code>​ </​code>​
  
-Python 
  
-<​code>​+<​details>​ 
 +<​summary>​Python</​summary>​ 
 + 
 +<​code ​python>
 # пока область поиска не пуста # пока область поиска не пуста
 while first <= last: while first <= last:
Строка 684: Строка 731:
 return False return False
 </​code>​ </​code>​
 +</​details>​
  
-PHP+<​details>​ 
 +<​summary>​PHP</​summary>​
  
-<​code>​+<​code ​php>
 <?php <?php
  
Строка 697: Строка 746:
 return false; return false;
 </​code>​ </​code>​
 +</​details>​
  
-Java+<​details>​ 
 +<​summary>​Java</​summary>​
  
-<​code>​+<​code ​java>
 // пока область поиска не пуста // пока область поиска не пуста
 while (first <= last) { while (first <= last) {
Строка 706: Строка 757:
 } }
 </​code>​ </​code>​
 +</​details>​
  
 ==== Недостатки бинарного поиска ==== ==== Недостатки бинарного поиска ====
Строка 719: Строка 771:
 И третье ограничение — некоторые данные просто нельзя упорядочить. Например,​ не существует какого-то естественного общепризнанного способа упорядочить цвета: И третье ограничение — некоторые данные просто нельзя упорядочить. Например,​ не существует какого-то естественного общепризнанного способа упорядочить цвета:
  
-{{https://​cdn2.hexlet.io/​derivations/​image/​original/​eyJpZCI6IjNlY2RiNmFmZTNiZjU5NGJhYTE3YWQwNTI4ODJhZTJhLnBuZyIsInN0b3JhZ2UiOiJjYWNoZSJ9?​signature=79405509d9f406a665a6eeb6edffe0ff249c44e89dcc7b9a3f1c7e00ec3a91cc|Цвета}}Таким же образом,​ сложно упорядочить пары чисел. Возьмем для примера широту и долготу — это как раз пара чисел:+{{ :basics_of_algorithms:​image_processing20231003-35-vql2f3.png |}} 
 + 
 +Таким же образом,​ сложно упорядочить пары чисел. Возьмем для примера широту и долготу — это как раз пара чисел:
  
   * Самый западный город России — Балтийск,​ его координаты 54°39′ с. ш. 19°55′ в. д.    * Самый западный город России — Балтийск,​ его координаты 54°39′ с. ш. 19°55′ в. д. 
Строка 765: Строка 819:
   * У метода перебора есть два варианта:​ Простой перебор,​ чтобы проверить,​ есть ли элемент в списке ​   * У метода перебора есть два варианта:​ Простой перебор,​ чтобы проверить,​ есть ли элемент в списке ​
  
-===== Для полного доступа к курсу нужен базовый план ===== 
- 
-Базовый план откроет полный доступ ко всем курсам,​ упражнениям и урокам Хекслета,​ проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент. 
- 
-[[:​subscription:​new?​nickname=professional_monthly_3900|Получить доступ]] 
- 
----- 
- 
-130 
- 
-[[:​courses|курсов]] 
- 
-1000 
- 
-упражнений 
- 
-2000+ 
- 
-часов теории 
- 
-3200 
  
-тестов 
basics_of_algorithms/binary_search.1696350060.txt.gz · Последние изменения: 2023/10/03 19:21 — werwolf