Зачем нужен хэш: от линейного поиска к O(1)
less_17__hash__set/theory_01__Why_do_we_need_hash.md
Мотивационный конспект: почему множество вообще существует как структура данных. Разбор идёт от линейного поиска O(n) к бинарному O(log n) (требует сортировки), а от него — к мечте об поиске за O(1), которая реализуется через хеширование. Отдельно вводится различие обычной (обратимой) функции и односторонней функции — хэш-функция как раз односторонняя: посчитать легко, восстановить исходное значение по хэшу нельзя.
- Линейный поиск: `for x in arr: if x == 99` — O(n)
- Бинарный поиск по отсортированному списку — O(log n)
- Идея адресации: значение → индекс ячейки за O(1)
- Обратимая функция vs односторонняя функция (`one-way function`)
- Особенности хэш-таблицы: только неизменяемые типы, возможны коллизии
- `x.__hash__()` у строки даёт число, у списка — `None` (TypeError при вызове)
Показать начало файла (124 строк всего)
## 1. Алгоритмы поиска
Представим себе, что у нас есть список:
```python
arr = [42, 17, 8, 99, 23, 56]
```
и нам нужно проверить, есть ли там число `99`.
### 1. Линейный поиск (naive search)
Самый простой способ — пройтись по всем элементам:
```python
for x in arr:
if x == 99:
print("Нашли!")
```
Время: **O(n)** — чем больше данных, тем дольше.
---
### 2. Бинарный поиск
Если список отсортирован:
```python
arr = [8, 17, 23, 42, 56, 99]
```
то можно искать быстрее — <a href="https://en.wikipedia.org/wiki/Binary_search#/media/File:Binary-search-work.gif" target="_blank">**бинарным поиском**</a>.
Суть: берём середину и отбрасываем половину данных на каждом шаге.
Время: **O(log n)** — быстро, но требует *упорядоченности*.
---
### Идея: а можно ли искать за O(1)?
То есть — мгновенно, без обходов и сортировок, вне зависимости от числа данных.
Да, если **мы сразу знаем, где лежит элемент**.
Например, как если бы у нас был словарь с адресами:
| Ключ | Адрес в памяти |
| ---- | -------------- |
| 42 | 0x001 |
| 17 | 0x002 |
| ... | ... |
Тогда поиск — это просто «сходить по адресу».
Вот ради этого и придумали **хеширование**.
---
## 2. Обычные и односторонние функции
Чтобы знать, *куда* класть объект, нужно вычислить **его адрес**.
Но мы не можем хранить адреса всех возможных значений (иначе теряет смысл сама идея мгновенного поиска).
…