-
Notifications
You must be signed in to change notification settings - Fork 16
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
d7eeee2
commit 56842a2
Showing
6 changed files
with
451 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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? |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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] | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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. |
Oops, something went wrong.