Что такое амортизированная сложность?
- Почему добавление в динамический массив считается O(1), если иногда нужно копирование?
- Чем амортизированная сложность отличается от средней?
Амортизированная сложность — средняя стоимость операции в длинной серии: редкие дорогие операции «размазываются» по многим дешёвым.
- Пример: добавление в динамический массив — обычно O(1), иногда копирование O(n), в среднем O(1)
- Это гарантия на серию, а не вероятность: не путать со средним случаем по случайным данным
А ещё Ключ — массив растёт в разы (×2 или ×1,5), а не на фиксированное число
Подробно
Некоторые структуры данных иногда выполняют дорогую операцию, но так редко, что в сумме по серии стоимость на одну операцию остаётся маленькой.
Классический пример — динамический массив (list в Python, ArrayList в Java, vector в C++). Пока есть свободное место, добавление в конец — O(1). Когда место кончилось, выделяется массив вдвое больше и все элементы копируются — O(n). Посчитаем суммарную работу для n добавлений: копирования происходят при размерах 1, 2, 4, 8, …, n, их сумма меньше 2n. Плюс n простых вставок. Итого меньше 3n операций на n добавлений, то есть O(1) на операцию в среднем по серии.
Важно, что массив растёт в разы. Если бы он увеличивался на 10 элементов, копирований было бы n/10, каждое до n элементов — итого O(n²) на серию, O(n) на операцию.
Отличие от средней сложности: средняя считается по распределению входных данных (например, хеш-таблица при «хорошем» хеше). Амортизированная — это гарантия для любой последовательности операций, без вероятностей.
Другие примеры: расширение хеш-таблицы, очередь на двух стеках, система непересекающихся множеств (union-find).
Пример
import sys
a = []
prev = sys.getsizeof(a)
for i in range(20):
a.append(i)
size = sys.getsizeof(a)
if size != prev: # память выделяется скачками, а не на каждый append
print(f"после {len(a)} элементов: {size} байт")
prev = sizeЧто хотят услышать
- Определение через стоимость серии операций.
- Разбор динамического массива с подсчётом.
- Почему рост должен быть в разы.
- Отличие от средней сложности.
Частые ошибки
- Говорить, что добавление в динамический массив «всегда O(1)».
- Путать амортизированную сложность со средним случаем.
Проверьте себя
Один верный вариант. Подумайте, потом откройте ответ.
Показать варианты и ответ
- ✗Средняя сложность операции на случайных входных данных: если входы распределены равномерно, дорогие случаи встречаются редко и в среднем дают O(1)
- ✓Средняя стоимость операции в длинной серии: редкие дорогие операции распределяются по многим дешёвым, как append в динамический массив
- ✗Это сложность в лучшем случае
- ✗Динамический массив растёт на фиксированные 10 элементов и даёт амортизированное O(1)
Что спросят дальше
Связанные вопросы
Разбор собеседования с sotto
После собеседования sotto разбирает разговор: оценка, каждый вопрос — хорошо, частично или слабо, чего не хватило в ответе и над чем поработать к следующему разу. Первые 30 минут бесплатно.