Skip to content

Commit

Permalink
theoretical material (#44)
Browse files Browse the repository at this point in the history
  • Loading branch information
Matvey-cmd authored Jun 17, 2024
1 parent d7eeee2 commit 56842a2
Show file tree
Hide file tree
Showing 6 changed files with 451 additions and 1 deletion.
103 changes: 102 additions & 1 deletion doc/README.md
Original file line number Diff line number Diff line change
@@ -1 +1,102 @@
# Теория по алгоритмам:
ПРОГРАММА “АЛГОРИТМЫ” ВЕСНА 2024 ФАЛТ.

# ВВЕДЕНИЕ

1 лекция.

- Определение алгоритма. Примеры простых алгоритмов: вычисление числа Фибоначчи, проверка числа на простоту, быстрое возведение в степень.
- Асимптотические обозначения, работа с ними.
- Определение структуры данных, абстрактного типа данных (интерфейса).
- Массив. Линейный поиск. Бинарный поиск.

# ТЕМА 1. БАЗОВЫЕ СТРУКТУРЫ ДАННЫХ

1 лекция.

- Динамический массив.
- Амортизационный анализ. Метод потенциалов. Метод монето
- Амортизированное (учетное) время добавления элемента в динамический массив.
- Двусвязный и односвязный список. Операции. Объединение списков.
- Стек.
- Очередь.
- Дек.
- Хранение стека, очереди и дека в массиве. Циклическая очередь в массиве.
- Хранение стека, очереди и дека в списке.
- Поддержка минимума в стеке.
- Представление очереди в виде двух стеков. Время извлечения элемента.
- Поддержка минимума в очереди.
- Двоичная куча. АТД “Очередь с приоритетом”.

# ТЕМА 2. СОРТИРОВКИ И ПОРЯДКОВЫЕ СТАТИСТИКИ

3 лекции.

- Формулировка задачи. Устойчивость.
- Квадратичные сортировки: сортировка вставками, выбором.
- Сортировка слиянием.
- Сортировка с помощью кучи.
- Нижняя оценка времени работы для сортировок сравнением.
- Поиск числа инверсий
- Быстрая сортировка. Выбор опорного элемента. Доказательство среднего времени работы.
- Сортировка подсчетом. Карманная сортировка.
- Поразрядная сортировка.
- MSD, LSD. Сортировка строк.
- Поиск k-ой порядковой статистики методом QuickSelect.
- Поиск k-ой порядковой статистики за линейное время.

# ТЕМА 3. ДЕРЕВЬЯ ПОИСКА

4 лекции.

- Определение дерева, дерева с корнем. Высота дерева, родительские, дочерние узлы, листья. Количество ребер.
- Обходы в глубину. pre-order, post-order и in-order для бинарных деревьев.
- Обход в ширину.
- Дерево поиска.
- Поиск ключа, вставка, удаление.
- Необходимость балансировки. Три типа самобалансирующихся деревьев.
- Декартово дерево. Оценка средней высоты декартового дерева при случайных приоритетах (без доказательства).
- Построение за O(n), если ключи упорядочены.
- Основные операции над декартовым деревом.
- АВЛ-дерево. Вращения.
- Оценка высоты АВЛ-дерева.
- Операции вставки и удаления в АВЛ-дереве.
- Красно-черное дерево.
- Оценка высоты красно-черного дерева.
- Операции вставки и удаления в красно-черном дереве.
- Сплей-дерево. Операция Splay.
- Поиск, вставка, удаление в сплей-дереве.
- Учетная оценка операций в сплей-дереве = O(log n) .
- B-деревья.

# ТЕМА 4. ХЕШ-ТАБЛИЦЫ

2 лекции.

- Хеш-функции. Остаток от деления, мультипликативная.
- Деление многочленов - CRC.
- Полиномиальная. Ее использование для строк. Метод Горнера для уменьшения количества операций умножения при ее вычислении.
- Хеш-таблицы. Понятие коллизии.
- Метод цепочек (открытое хеширование).
- Метод прямой адресации (закрытое хеширование).
- Линейное пробирование. Проблема кластеризации.
- Квадратичное пробирование.
- Двойное хеширование.

# ТЕМА 5. ЖАДНЫЕ АЛГОРИТМЫ И ДИНАМИЧЕСКОЕ ПРОГРАММИРОВАНИЕ

1 лекция.

- [Составляющие ДП (формула пересчета, порядок, база, где ответ)](topic5/question1.md)
- [Задача о кузнечике. Задача о черепахе](topic5/question2.md)
- [Задача о наибольшей общей подпоследовательности](topic5/question3.md)
- [Задача о наибольшей возрастающей подпоследовательности](topic5/question4.md)
- [Дерево отрезков для решения задачи о НВП](topic5/question5.md)

2 лекция

- Задача о рюкзаке. Жадный и динамический подходы
- Почему нет решения задачи о рюкзаке жадным методом?
- ДП на матрицах. Числа Фиббоначи
- ДП на матрицах. Кол-во путей в графе из u в v длины ровно k
- ДП на матрицах. Кол-во путей в графе из u в v длины <= k
- ДП на матрицах. Есть ли хотя бы один путь из u в v длины ровно k?
50 changes: 50 additions & 0 deletions doc/topic5/question1.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# Составляющие ДП (формула пересчета, порядок, база, где ответ)Составляющие ДП (формула пересчета, порядок, база, где ответ)

**Динамическое программирование** — это когда у нас есть задача, которую непонятно как решать, и мы разбиваем ее на меньшие задачи, которые тоже непонятно как решать.

Чтобы успешно решить задачу динамикой нужно:
1) Состояние динамики: параметр(ы), однозначно задающие подзадачу.
2) Значения начальных состояний.
3) Переходы между состояниями: формула пересчёта.
4) Порядок пересчёта.
5) Положение ответа на задачу: иногда это сумма или, например, максимум из значений нескольких состояний.

## Порядок пересчёта

Существует три порядка пересчёта:
**1)** Прямой порядок:
Состояния последовательно пересчитывается исходя из уже посчитанных.![](https://habrastorage.org/r/w1560/storage3/f1f/36c/875/f1f36c87585e05a9beb692324fa6b72e.png)

**2)** Обратный порядок:
Обновляются все состояния, зависящие от текущего состоянияю.![](https://habrastorage.org/r/w1560/storage3/0ae/3a1/bf4/0ae3a1bf4aed4161e8375305693cbf69.png)

**3)** Ленивая динамика:
Рекурсивная мемоизированная функция пересчёта динамики. Это что-то вроде поиска в глубину по ацикличному графу состояний, где рёбра — это зависимости между ними.
![](https://habrastorage.org/r/w1560/storage3/045/d67/fbe/045d67fbe78f0d724d75dd89a352cfe2.png)

**Прямой порядок:**
```python
fib[1] = 1 # Начальные значения
fib[2] = 1 # Начальные значения
for i in range(3, n + 1):
fib[i] = fib[i - 1] + fib[i - 2] # Пересчёт состояния i
```

**Обратный порядок:**
```python
fib[1] = 1 # Начальные значения
for i in range(1, n):
fib[i + 1] += fib[i] # Обновление состояния i + 1
fib[i + 2] += fib[i] # Обновление состояния i + 2
```

**Ленивая динамика:**
```python
def get_fib(i):
if (i <= 2): # Начальные значения
return 1
if (fib[i] != -1): # Ленивость
return fib[i]
fib[i] = get_fib(i - 1) + get_fib(i - 2) # Пересчёт
return fib[i]
```
62 changes: 62 additions & 0 deletions doc/topic5/question2.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# Задача о кузнечике. Задача о черепахе

## Задача о кузнечике:
Рассмотрим следующую задачу. На числовой прямой сидит кузнечик, который может прыгать вправо на одну или на две единицы. Первоначально кузнечик находится в точке с координатой 0.
Определите количество различных маршрутов кузнечика, приводящих его в точку с координатой n.

**Рекурсивное решение:**
```python
# неэффективное решение
def F(n):
if n < 2:
return 1
else:
return F(n - 1) + F(n - 2)
```

**Нерекурсивное решение: **
```python
F = [0] * (n + 1)
F[0] = 1
F[1] = 1
for i in range(2, n + 1):
F[i] = F[i - 2] + F[i — 1]
```

## Модификации задачи о кузнечике:
Модифицируем задачу. Пусть кузнечик прыгает на одну, две или три единицы, необходимо также вычислить количество способов попасть в точку n. В рекуррентном соотношении добавится еще одно слагаемое: F(n) = F(n - 1) + F(n - 2) + F(n - 3). И начальные значения для вычисления
теперь должны состоять из трех чисел: F(0), F(1), F(2). Решение изменится не сильно:

```python
F = [0] * (n + 1)
F[0] = 1
F[1] = F[0]
F[2] = F[1] + F[0]
for i in range(3, n + 1):
F[i] = F[i - 3] + F[i — 2] + F[i — 1]
```

## Задача про черепашку:
Эволюционируем от кузнечика к черепахе. Черепашка перемещается по прямоугольному полю n×m и собирает цветочки. На клетке (i,j) растет cij
цветочков. Изначально черепашка стоит в клетеке (0,0), а ей надо добраться до клетки (n−1,m−1), собрав как можно больше цветочков. Двигаться она может только на одну клетку вниз или на одну клетку вправо за раз.

Решение во многом похоже на задачу про кузнечика:

dp[i][j]
- состояние динамики, равное максимальному количеству цветочков, которое можно набрать по пути до клетки (i,j)
.
dp[i][j]=max(dp[i−1][j],dp[i][j−1])+cij
- правило пересчета
Порядок обхода - надо проходить через клетки так, чтобы все состояния, которые нужны для пересчета, уже были валидны. Можно во внешнем цикле перебирать строку, а во внутреннем столбец по возрастанию. Восстановление ответа аналогично задаче про кузнечика. Расход времени и памяти составит O(n*m).

## Количество путей:
Забудем пока про цветочки. Пусть теперь неокторые клетки поля заблокированы, черепашка не может заходить на них. Мы хотим найти, сколькими способами черепашка может добраться до клетки (n−1,m−1).

Пусть dp[i][j]
- количество способов добраться до клетки (i,j)
из начальной. Формула пересчета тогда будет следующей: dp[i][j]=dp[i−1[j]+dp[i][j−1].
То есть в клетку (i,j) можно пройти либо из клетки над ней, либо слева от нее.

Заметим, что такое правило пересчета разрешает нам ходить по заблокированным клеткам в общем случае. Это можно исправить так: при обходе поля и подсчете состояний можно не считать способы для заблокированных клеток, значение динамики в них всегда будет 0, что равносильно запрету посещать клетку.

Какие стартовые значения нам нужны? Пока что мы знаем только, что в исходную клетку можно пройти единственным способом - остаться в ней, поэтому dp[0][0]=1.
Loading

0 comments on commit 56842a2

Please sign in to comment.