Оценка сложности алгоритма
Big O нотация, или Как оценить сложность алгоритма
Что такое алгоритм
Алгоритм - набор действий (инструкция), который компьютер может выполнить и который приведёт к нужному нам результату.
Как измерить сложность алгоритма
Просто измерять время выполнения двух алгоритмов не вариант, ибо один алгоритм может быстрее обработать 10 чисел, но в задаче с 1кк чисел он окажется медленнее, так как 2-й алгоритм может быть лучше оптимизирован именно под работу с большим кол-вом чисел.
Приходится придумывать вариант посложнее, который поможет оценить работу алгоритма с разными объёмами данных. Нужно описать связь между кол-вом операций и элементов. В математике это позволяет сделать подобная функция
значение будет зависеть от значения по определённому правилу.
будет всегда в раза больше .
Зависимость может быть любой - главное, что есть инструмент, с помощью которого можно описать такую зависимость.
Например, мы можем сравнить:
Если - это зарплата, а - кол-во отработанных дней, мы и без калькулятора можно сделать выбор между этими двумя предложениями.
В нашем случае - кол-во действий, которые алгоритм должен совершить, а - кол-во элементов, которые он должен обработать.
Если возьмём простую зависимость:
то по такому описанию поймём, что алгоритм на каждый элемент выполняет по 2 действия. А значит, если нам надо будет обработать 100 элементов, алгоритм сделает это за 200 действий:
, и чаще используются в школьных задачах. Когда речь заходит об оценке сложности алгоритмов, принято использовать следующие обозначения:
- кол-во элементов;
- функция от кол-ва элементов (по сути, это и есть или ).
Буквы другие, но суть та же - они сразу позволяют понять, что речь идёт о задаче оценки сложности алгоритмов.
Типичные примеры O-нотации (сложности алгоритмов)
Никаких сложных точных уравнений писать не нужно. Есть несколько общих вариантов зависимости, которые позволяют примерно оценить скорость работы алгоритма. По сути, не столько важно конкретное кол-во действий алгоритма, сколько важен порядок роста.
То есть мы отвечаем на вопросы вида: «Если алгоритм обработает 10 элементов за X действий, во сколько раз больше действий ему понадобится на 1 000 элементов?».
Ниже по порядку возрастания сложности все варианты:
-
- в этом случае у нас нет числа n, как нет и зависимости от кол-ва элементов. Такая оценка может быть, например, у алгоритмов, которые выполняют действие над одним элементом.
Допустим, извлекают одну букву из строки. В строке может быть млрд букв, а может быть 10, но первую букву можно извлечь за одно действие. -
- может пугать, но достаточно просто запомнить, что эта оценка быстрее линейной зависимости. Если при линейной зависимости на 128 элементов мы потратим 128 действий, то при :
- нам понадобится всего 7 действий.
Кол-во действий будет расти с кол-вом элементов, но происходить это будет гораздо медленнее. -
- линейная оценка, самая простая (но не самая эффективная, как мы видели ранее).
Сколько элементов - столько и действий. -
- пожалуй, самая длинная из вариантов, она говорит о том, что алгоритм работает медленнее, чем при линейной оценке. Можем пересчитать пример со 128 элементами:
Получается значительная разница (и чем больше элементов - тем она будет существеннее). -
- квадратичная зависимость, она ещё более медленная, чем предыдущая. Если там мы умножали , здесь нам пришлось бы умножать на
-
- самая медленная оценка из базовых - факториал от числа элементов, который надо обработать. Для обработки 128 элементов пришлось бы считать следующую цепочку:
~ - это число намного больше предыдущего большого числа.
Наглядно
Допустим, задача - разделить лист бумаги на 16/256/1024 прямоугольников.
Пусть компьютер выполняет 10 операций в секунду. Если мы выберем для решения задачи алгоритм со сложностью , то для получения 16 прямоугольников нам понадобится всего 4 операции, и они выполнятся за 0,4 с.