ИнтВиз

Алгоритмы · модуль 12 из 14

Асимптотика: почему алгоритм важнее железа

Сколько операций выполнит алгоритм на n элементах и сколько это займёт на процессоре с 10⁹ операций в секунду. Сдвиньте n и посмотрите, какие алгоритмы перестают быть пригодными.

Ось операций логарифмическая: каждое деление в 10 раз больше предыдущего.

КлассПримерОперацийВремя при 10⁹ оп/с

Число сравнений в сортировках (посчитано на сервере)

Сортировкаn = 100n = 1 000n = 2 000n = 10 000

Теория

Сложность алгоритма описывает, как растёт число операций при росте размера входных данных $n$. Запись $f(n) = O(g(n))$ означает, что начиная с некоторого $n$ функция $f$ растёт не быстрее, чем $g$, с точностью до постоянного множителя:

$$ f(n) = O(g(n)) \iff \exists\, C > 0,\ n_0:\ f(n) \le C \cdot g(n) \ \text{для всех}\ n \ge n_0. $$

Основные классы роста, от медленного к быстрому:

Класс Пример При $n = 10^6$
$O(1)$ поиск ключа в словаре 1 операция
$O(\log n)$ бинарный поиск около 20 операций
$O(n)$ линейный поиск $10^6$ операций
$O(n \log n)$ сортировка слиянием около $2 \cdot 10^7$ операций
$O(n^2)$ сортировка пузырьком $10^{12}$ операций
$O(2^n)$ перебор подмножеств больше $10^{300\,000}$ операций

Время работы оценивается как $T(n) \approx f(n) / 10^9$ секунд для процессора, выполняющего около $10^9$ простых операций в секунду. Постоянные множители и младшие слагаемые в O-нотации отбрасываются: $3n^2 + 100n$ и $n^2/2$ относятся к одному классу $O(n^2)$.

На логарифмической шкале степенные функции превращаются в прямые с наклоном, равным показателю степени, а экспонента $2^n$ растёт быстрее любой степени.

Где это применяется в IT

Сложность оценивают раньше, чем замеряют время: на код-ревью и на собеседованиях. Новый процессор ускорит программу в 2 раза, а замена алгоритма $O(n^2)$ на $O(n \log n)$ при $n = 10^6$ даёт ускорение примерно в 50 000 раз.

  • Словари и множества. Поиск по ключу в dict и set выполняется в среднем за $O(1)$.
  • Сортировка. list.sort() и sorted() в Python используют Timsort со сложностью $O(n \log n)$.
  • Полный перебор. Алгоритмы $O(2^n)$ применимы только при $n$ до 30–40; дальше нужны эвристики или динамическое программирование.

Код на Python

Загружаю пример…