Сложность алгоритмов: O(n), O(log n), O(n²) на пальцах
Когда разработчик говорит, что алгоритм работает за O(n log n) — это не мистика и не математика для гениев.
Это просто способ выразить, насколько быстро (или медленно) алгоритм ведёт себя при росте объёма данных.
Это Big O Notation — обозначение асимптотической сложности. Оно показывает, как изменяется время работы или количество операций при росте входных данных
Важно: Big O не даёт точного времени, только порядок роста.
Пример:
Пример на Python:
Пример на C:
Пример: найти элемент в отсортированном массиве двоичным поиском.
Если элементов 1 000 000 — двоичный поиск сделает максимум 20 шагов.
Это логарифм по основанию 2:
Алгоритм двоичного поиска на каждом шаге делит массив пополам. Количество шагов, нужных чтобы "сжать" диапазон до одного элемента — это:
Где:
log2(1 000 000)≈19.93
Добавляем 1 (последний шаг сравнения) → округляем до целого: будет 20.
Пример:
Если данных в 10 раз больше — будет 10 раз больше операций.
Пример на C — сортировка пузырьком:
1000 элементов → миллион сравнений.
Вопрос к читателю: какой алгоритм у тебя был настолько неэффективный, что ты его потом переписал с нуля? Делись примерами 
Это просто способ выразить, насколько быстро (или медленно) алгоритм ведёт себя при росте объёма данных.
Что такое "O" вообще?
Это Big O Notation — обозначение асимптотической сложности. Оно показывает, как изменяется время работы или количество операций при росте входных данных
n
.
Пример:
O(n)
= "если данных в 2 раза больше, то и времени нужно в 2 раза больше".
O(1) — константное время
- Пример: получить элемент массива по индексу —
arr[5]
- Сколько бы ни было данных, операция всегда занимает одинаковое время
- Быстро, стабильно, идеально

Python:
arr = [3, 8, 13, 21]
x = arr[2] # O(1)

C:
int arr[] = {3, 8, 13, 21};
int x = arr[2]; // O(1)
O(log n) — логарифмическое время
- Делим задачу пополам каждый раз
- Часто встречается в двоичном поиске, деревьях, оптимизированных алгоритмах
- Очень хорошо масштабируется!

Python:
# O(log n)
def binary_search(arr, target):
left, right = 0, len(arr) - 1
while left <= right:
mid = (left + right) // 2
if arr[mid] == target:
return mid
elif arr[mid] < target:
left = mid + 1
else:
right = mid - 1
return -1

Это логарифм по основанию 2:
Алгоритм двоичного поиска на каждом шаге делит массив пополам. Количество шагов, нужных чтобы "сжать" диапазон до одного элемента — это:
Код:
максимальное количество шагов=log₂(n)+1
Где:
n
— количество элементов,log₂(n)
— логарифм по основанию 2 (то есть: сколько раз можно делить на 2).
Пример: n = 1 000 000
log2(1 000 000)≈19.93Добавляем 1 (последний шаг сравнения) → округляем до целого: будет 20.
Табличка: для наглядности
Кол-во элементов: n | log₂n | Шагов |
---|---|---|
1 | 0 | 1 |
10 | ≈ 3.3 | 4 |
1000 | ≈ 9.96 | 10 |
1 000 000 | ≈ 19.93 | 20 |
1 000 000 000 | ≈ 29.9 | 30 |
O( n ) — линейное время
- Простой перебор: от начала до конца
- Хуже, чем
log n
, но иногда — единственный способ - Часто встречается в задачах на поиск, фильтрацию, подсчёт

Python:
# O(n)
def contains(arr, target):
for x in arr:
if x == target:
return True
return False

O(n²) — квадратичное время
- Каждый элемент сравнивается с каждым
- Работает медленно при большом объёме
- Встречается в пузырьковой сортировке, наивных реализациях

C:
void bubble_sort(int arr[], int size) {
for (int i = 0; i < size; i++) {
for (int j = 0; j < size - 1; j++) {
if (arr[j] > arr[j + 1]) {
int tmp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = tmp;
}
}
}
}

Вывод
- Понимание сложности — фундамент любой алгоритмики
- Не всегда нужен самый быстрый алгоритм — главное: подходящий по задаче
- Если можешь улучшить
O(n²)
доO(n log n)
— делай это!

