Review the ru version with Codex. (#1870)

This commit is contained in:
Yudong Jin
2026-03-30 07:27:40 +08:00
committed by GitHub
parent 7a78369e4c
commit fe6443235b
97 changed files with 769 additions and 767 deletions
+2 -2
View File
@@ -1,6 +1,6 @@
# Двоичный поиск
<u>Двоичный поиск (binary search)</u> - это эффективный алгоритм поиска, основанный на стратегии "разделяй и властвуй". Он использует упорядоченность данных и на каждом шаге сокращает область поиска вдвое, пока не найдет целевой элемент или пока интервал поиска не опустеет.
<u>Двоичный поиск (binary search)</u> - это эффективный алгоритм поиска, основанный на стратегии "разделяй и властвуй". Он использует упорядоченность данных, сокращая на каждом шаге область поиска вдвое, пока не будет найден целевой элемент или пока интервал поиска не опустеет.
!!! question
@@ -55,7 +55,7 @@
## Методы представления интервалов
Помимо описанного выше двойного замкнутого интервала, часто используется и интервал "слева закрыт, справа открыт", который задается как $[0, n)$ , то есть левая граница включается, а правая - нет. В этом представлении интервал $[i, j)$ пуст, когда $i = j$ .
Помимо описанного выше двойного замкнутого интервала, часто используется и левозамкнутый правооткрытый интервал, который задается как $[0, n)$ , то есть левая граница включается, а правая - нет. В этом представлении интервал $[i, j)$ пуст, когда $i = j$ .
На основе этого представления можно реализовать двоичный поиск с той же функциональностью:
@@ -6,7 +6,7 @@
Дан упорядоченный массив `nums` длины $n$, который может содержать повторяющиеся элементы. Верните индекс самого левого элемента `target` в массиве. Если массив не содержит этот элемент, верните $-1$ .
Вспомним метод поиска точки вставки при двоичном поиске: после завершения поиска указатель $i$ указывает на самый левый `target` , **поэтому поиск точки вставки по сути и есть поиск индекса самого левого `target`**.
Вспомним метод поиска точки вставки при двоичном поиске: после завершения поиска указатель $i$ указывает на самый левый `target` , **поэтому поиск точки вставки по сути является поиском индекса самого левого `target`**.
Рассмотрим реализацию поиска левой границы через функцию поиска точки вставки. Обратите внимание: массив может не содержать `target` , и тогда возможны две ситуации.
@@ -1,4 +1,4 @@
# Точка вставки при двоичном поиске
# Двоичный поиск точки вставки
Двоичный поиск можно использовать не только для поиска целевого элемента, но и для решения многих вариаций задачи, например для поиска позиции вставки целевого элемента.
@@ -18,7 +18,7 @@
**Вопрос 2**: если массив не содержит `target` , индекс какого элемента будет точкой вставки?
Рассмотрим процесс двоичного поиска подробнее: когда `nums[m] < target` , указатель $i$ сдвигается, а значит, приближается к элементу, который больше либо равен `target` . Аналогично указатель $j$ все время приближается к элементу, который меньше либо равен `target` .
Рассмотрим процесс двоичного поиска подробнее: когда `nums[m] < target` , указатель $i$ сдвигается вправо и тем самым приближается к элементу, который больше либо равен `target` . Аналогично указатель $j$ постепенно приближается к элементу, который меньше либо равен `target` .
Следовательно, после завершения двоичного поиска обязательно выполняется следующее: указатель $i$ указывает на первый элемент, больший `target` , а указатель $j$ указывает на первый элемент, меньший `target` . **Нетрудно сделать вывод, что если массив не содержит `target` , то индекс вставки равен $i$** . Код приведен ниже:
@@ -74,7 +74,7 @@
=== "<8>"
![binary_search_insertion_step8](binary_search_insertion.assets/binary_search_insertion_step8.png)
Если посмотреть на следующий код, то видно, что операции в ветвях `nums[m] > target` и `nums[m] == target` совпадают, поэтому эти две ветви можно объединить.
Если посмотреть на следующий код, то видно, что действия в ветвях `nums[m] > target` и `nums[m] == target` совпадают, поэтому эти две ветви можно объединить.
Даже в этом случае можно оставить условия развернутыми, потому что так логика выглядит более ясной и код легче читать.
@@ -86,6 +86,6 @@
Код в этом разделе записан в стиле "двойного замкнутого интервала". При желании можно самостоятельно реализовать вариант "слева закрыт, справа открыт".
Если смотреть в целом, суть двоичного поиска сводится к тому, что для указателей $i$ и $j$ заранее задаются цели поиска; целью может быть конкретный элемент (например, `target` ), а может быть и диапазон элементов (например, элементы, меньшие `target` ).
Если смотреть в целом, суть двоичного поиска сводится к тому, что для указателей $i$ и $j$ заранее задаются ориентиры поиска; целью может быть конкретный элемент, например `target` , а может быть и диапазон элементов, например все элементы, меньшие `target` .
В ходе непрерывного двоичного деления указатели $i$ и $j$ постепенно приближаются к заранее заданной цели. В конце они либо успешно находят ответ, либо останавливаются после выхода за границы.
+2 -2
View File
@@ -4,6 +4,6 @@
!!! abstract
Поиск - это приключение в неизвестность: иногда приходится пройти каждый уголок загадочного пространства, а иногда удается быстро зафиксировать цель.
Поиск - это движение в неизвестность: иногда приходится пройти каждый уголок пространства, а иногда удается быстро найти цель.
В этом путешествии каждый новый шаг может привести к ответу, которого мы не ожидали.
В этом пути каждый новый шаг может привести к ответу, которого мы не ожидали.
@@ -1,4 +1,4 @@
# Стратегии хеш-оптимизации
# Стратегии оптимизации хеширования
В алгоритмических задачах **мы часто заменяем линейный поиск на хеш-поиск, чтобы уменьшить временную сложность алгоритма**. Разберем одну задачу, чтобы лучше понять этот прием.
@@ -7,14 +7,14 @@
- **Поиск целевого элемента путем обхода структуры данных**, например обход массива, списка, дерева или графа.
- **Эффективный поиск элементов с использованием структуры организации данных или априорной информации**, например двоичный поиск, хеш-поиск и поиск в двоичном дереве поиска.
Нетрудно заметить, что эти темы уже рассматривались в предыдущих главах, поэтому алгоритмы поиска нам уже знакомы. В этом разделе мы еще раз посмотрим на них, но уже более системно.
Нетрудно заметить, что эти темы уже рассматривались в предыдущих главах, поэтому алгоритмы поиска нам уже знакомы. В этом разделе мы систематизируем полученные ранее знания и еще раз посмотрим на них как на единую группу методов.
## Полный перебор
Полный перебор заключается в том, что мы обходим каждый элемент структуры данных, чтобы найти целевой элемент.
- "Линейный поиск" применяется к линейным структурам данных, таким как массивы и списки. Он начинается с одного конца структуры данных и последовательно проверяет элементы, пока не найдет целевой элемент или пока не достигнет другого конца структуры данных.
- "Поиск в ширину" и "поиск в глубину" - это две стратегии обхода графов и деревьев. Поиск в ширину стартует из начального узла и исследует все узлы текущего уровня, прежде чем переходить к следующему. Поиск в глубину стартует из начального узла, проходит один путь до конца, затем возвращается назад и пробует другие пути, пока не будет полностью пройдена вся структура данных.
- "Обход в ширину" и "обход в глубину" - это две стратегии обхода графов и деревьев. Обход в ширину стартует из начального узла и исследует все узлы текущего уровня, прежде чем переходить к следующему. Обход в глубину стартует из начального узла, проходит один путь до конца, затем возвращается назад и пробует другие пути, пока не будет полностью пройдена вся структура данных.
Преимущество полного перебора состоит в его простоте и универсальности, **поскольку он не требует предварительной обработки данных и использования дополнительных структур данных**.
@@ -28,13 +28,13 @@
- "Хеш-поиск" использует хеш-таблицу для построения отображения между поисковыми данными и целевыми данными, благодаря чему запросы выполняются эффективно.
- "Поиск в дереве" ведется в конкретной древовидной структуре (например, в двоичном дереве поиска) и позволяет быстро отсекать узлы на основе сравнения значений, чтобы найти цель.
Преимущество этих алгоритмов в высокой эффективности, **их временная сложность может достигать $O(\log n)$ и даже $O(1)$** .
Преимущество этих алгоритмов заключается в высокой эффективности: **их временная сложность может достигать $O(\log n)$ и даже $O(1)$** .
Однако **для использования таких алгоритмов обычно требуется предварительная обработка данных**. Например, для двоичного поиска нужно заранее отсортировать массив, а хеш-поиск и поиск в дереве требуют дополнительных структур данных, поддержание которых тоже отнимает время и память.
!!! tip
Адаптивные алгоритмы поиска часто называют алгоритмами поиска в узком смысле, **поскольку они в основном предназначены для быстрого поиска целевого элемента в конкретной структуре данных**.
Адаптивные алгоритмы поиска часто называют алгоритмами поиска в узком смысле, **поскольку они в основном предназначены для быстрого нахождения целевого элемента в конкретной структуре данных**.
## Выбор метода поиска
+1 -1
View File
@@ -3,7 +3,7 @@
### Ключевые выводы
- Двоичный поиск опирается на упорядоченность данных и выполняет поиск путем циклического сокращения интервала вдвое. Он требует упорядоченных входных данных и подходит только для массивов или структур данных, реализованных на их основе.
- Полный перебор находит данные путем обхода структуры данных. Линейный поиск подходит для массивов и списков, а поиск в ширину и поиск в глубину подходят для графов и деревьев. Эти алгоритмы универсальны и не требуют предварительной обработки данных, но их временная сложность $O(n)$ сравнительно велика.
- Полный перебор находит данные путем обхода структуры данных. Линейный поиск подходит для массивов и списков, а обход в ширину и обход в глубину подходят для графов и деревьев. Эти алгоритмы универсальны и не требуют предварительной обработки данных, но их временная сложность $O(n)$ сравнительно велика.
- Хеш-поиск, поиск в дереве и двоичный поиск относятся к эффективным методам поиска и позволяют быстро находить целевой элемент в конкретных структурах данных. Такие алгоритмы обладают высокой эффективностью, их временная сложность может достигать $O(\log n)$ и даже $O(1)$ , но обычно им нужны дополнительные структуры данных.
- На практике нужно анализировать размер данных, требования к производительности поиска, а также частоту запросов и обновлений данных, чтобы выбрать подходящий метод поиска.
- Линейный поиск подходит для небольших или часто обновляемых наборов данных; двоичный поиск - для больших отсортированных данных; хеш-поиск - для сценариев с высокими требованиями к скорости запросов и без необходимости поиска по диапазону; поиск в дереве - для больших динамических данных, где нужно поддерживать порядок и выполнять диапазонные запросы.