This commit is contained in:
krahets
2026-07-19 03:42:10 +08:00
parent cb5235bc3f
commit 2b8612bc41
238 changed files with 7477 additions and 3 deletions
+107
View File
@@ -0,0 +1,107 @@
---
comments: true
---
<!-- Автоматически создано utils/exercises/publish_exercises.py; не редактируйте напрямую. -->
# 6.5 &nbsp; Упражнения
## 6.5.1 &nbsp; Вопросы для самопроверки
### 1. &nbsp; Как искать после хеш-коллизии
Хеш-таблица содержит 5 бакетов и использует хеш-функцию $h(x)=x \bmod 5$. При коллизии элементы последовательно добавляются в список соответствующего бакета.
В таблицу по порядку вставляют `[1, 6, 11, 7]`.
<!-- numbered-subquestions -->
1. Запишите содержимое бакетов с номерами 0–4.
2. В какой бакет сначала попадает поиск числа 6 и какие элементы проверяются по порядку?
3. Исходя из содержимого бакетов в вопросе 1, перезаписали ли позднее вставленные элементы более ранние? Объясните ответ с учетом этого способа разрешения коллизий.
??? success "Ответ"
1. Так как $1\bmod5=6\bmod5=11\bmod5=1$, а $7\bmod5=2$, бакеты имеют вид:
```text
0: []
1: [1, 6, 11]
2: [7]
3: []
4: []
```
2. При поиске числа 6 сначала выбирается бакет 1, затем сравниваются элементы 1 и 6. Искомый элемент находится при втором сравнении.
3. Одинаковые хеш-значения означают лишь попадание элементов в один бакет, но не равенство самих элементов. При цепной адресации все столкнувшиеся элементы сохраняются в бакете,
а при поиске сравниваются по очереди. Поэтому 1, 6 и 11 не перезаписывают друг друга.
### 2. &nbsp; Куда перемещаются элементы при расширении хеш-таблицы
Хеш-таблица с цепной адресацией первоначально содержит 5 бакетов и использует хеш-функцию $h(x)=x\bmod5$.
Ключи `[1, 6, 11]` находятся в бакете 1.
Теперь таблицу расширяют до 7 бакетов, и хеш-функция принимает вид $h(x)=x\bmod7$.
<!-- numbered-subquestions -->
1. Вычислите новые номера бакетов для 1, 6 и 11.
2. Какие бакеты будут непустыми после расширения?
3. Можно ли при расширении скопировать список из прежнего бакета 1 без изменений в новый бакет 1? Обоснуйте ответ результатами вопросов 1 и 2.
??? success "Ответ"
1. Новые номера бакетов:
- $1\bmod7=1$;
- $6\bmod7=6$;
- $11\bmod7=4$.
2. В бакете 1 хранится 1, в бакете 4 — 11, а в бакете 6 — 6. Три ключа больше не находятся в одном бакете.
3. Копировать список без изменений нельзя. Номер бакета вычисляется как остаток от деления ключа на число бакетов. После замены 5 на 7 номер бакета для того же ключа может измениться,
поэтому положение каждого ключа необходимо вычислить заново. Если просто скопировать прежний бакет 1, то последующий поиск по новой формуле направится за 6 в бакет 6, а за 11 — в бакет 4
и не найдет эти ключи.
### 3. &nbsp; Можно ли найти 11 после удаления 6
Хеш-таблица содержит 5 позиций с индексами `04` и использует хеш-функцию $h(x)=x\bmod5$.
При коллизии поиск первого свободного места начинается с вычисленного хеш-функцией индекса и продолжается вправо.
В таблицу по порядку вставляют `[1, 6, 11]`.
<!-- numbered-subquestions -->
1. По какому индексу в итоге находится каждое из трех чисел?
2. Какие индексы проверяются по порядку при поиске 11?
3. Допустим, при удалении 6 его позицию просто освобождают, как если бы она никогда не использовалась, а поиск прекращается при встрече с пустой позицией.
Что произойдет при следующем поиске 11? Будет ли результат правильным? Если нет, как избежать ошибки?
??? success "Ответ"
1. Число 1 находится по индексу 1. Число 6 также отображается в индекс 1, но после коллизии помещается по индексу 2.
Число 11 тоже начинает поиск с индекса 1, пропускает занятые индексы 1 и 2 и в итоге помещается по индексу 3.
2. При поиске 11 последовательно проверяются индексы `1, 2, 3`, и число находится по индексу 3.
3. Если пометить индекс 2 как «никогда не использовавшийся», то поиск 11 остановится на индексе 2 после проверки индекса 1
и ошибочно решит, что числа 11 нет. При удалении следует оставлять отметку «удалено»:
встретив ее, поиск продолжает проверять следующий индекс (после индекса 4 возвращаясь к индексу 0), а при последующей вставке эту позицию можно использовать снова.
## 6.5.2 &nbsp; Задачи по программированию
### 1. &nbsp; Сравнение состава символов в двух строках
Даны две строки `s` и `t`, состоящие только из строчных английских букв.
Символы в `s` можно переставлять произвольным образом, но нельзя добавлять, удалять или заменять.
Определите, можно ли после перестановки получить `t`. Если можно, верните `true`, иначе — `false`.
Используйте хеш-таблицу для подсчета числа вхождений каждой буквы и не сортируйте символы в строках.
??? tip "Подсказки"
1. Если строки имеют разную длину, их состав символов не может совпадать
2. Сохраняйте в хеш-таблице количество каждой буквы; при обходе s увеличивайте соответствующий счетчик на 1
3. При обходе t уменьшайте соответствующий счетчик на 1; состав символов совпадает, только если все счетчики в конце равны 0
[LeetCode](https://leetcode.com/problems/valid-anagram/){ .rounded-button .exercise-button target="_blank" rel="noopener noreferrer" }
+1
View File
@@ -19,3 +19,4 @@ icon: material/table-search
- [6.2 &nbsp; Хеш-коллизии](hash_collision.md)
- [6.3 &nbsp; Алгоритмы хеширования](hash_algorithm.md)
- [6.4 &nbsp; Резюме](summary.md)
- [6.5 &nbsp; Упражнения](exercises.md)