Чтобы проанализировать алгоритм, вы не хотите идти построчно, спрашивая "сколько времени дает эта конкретная строка?" Причина в том, что каждая строка не выполняется одинаковое количество раз. Например, самая внутренняя строка выполняется целую кучу раз, по сравнению с первой строкой, которая запускается только один раз.
Чтобы проанализировать алгоритм, подобный этому, попробуйте определить некоторую величину, значение которой находится в постоянном множителе общего времени выполнения алгоритма. В этом случае эта величина, вероятно, будет равна «сколько раз строка sum++
выполняется?», Так как, если мы знаем это значение, мы знаем общее количество времени, потраченное двумя циклами в алгоритме. Чтобы понять это, давайте проследим, что происходит с этими циклами. На первой итерации внешнего цикла i == 0
и внутренний цикл будет выполняться ровно один раз (с 0 по 0). На второй итерации внешнего цикла i == 1
и внутренний цикл выполняется ровно дважды (сначала с j == 1
, один раз с j == 0
. В более общем смысле, на k-й итерации внешнего цикла внутренний цикл выполняет k + 1
Это означает, что общее число итераций самого внутреннего цикла определяется как
1 + 2 + 3 + ... + N
Эта величина может быть показана равной
N (N + 1) N^2 + N N^2 N
--------- = ------- = --- + ---
2 2 2 2
Из этих двух терминов термин N^2 / 2
является доминирующим термином роста, и поэтому, если мы игнорируем его постоянные факторы, мы получаем время выполнения O (N 2 ).
Не смотрите на этот ответ как на то, что вы должны запомнить - подумайте обо всех шагах, необходимых для получения ответа. Мы начали с поиска некоторой величины для подсчета, а затем увидели, как на эту величину повлияло выполнение циклов. Из этого мы смогли вывести математическое выражение для этой величины, которое затем упростили. Наконец, мы взяли результирующее выражение и определили доминантный термин, который служит в качестве big-O для всей функции.