В чем сложность этого алгоритма суммирования?
#include <stdio.h>
int main() {
int N = 8; /* for example */
int sum = 0;
for (int i = 1; i <= N; i++)
for (int j = 1; j <= i*i; j++)
sum++;
printf("Sum = %d\n", sum);
return 0;
}
для каждого значения n (i переменной), j значений будет n ^ 2. Таким образом, сложность будет равна n. n ^ 2 = n ^ 3. Это правильно?
Если проблема будет:
#include <stdio.h>
int main() {
int N = 8; /* for example */
int sum = 0;
for (int i = 1; i <= N; i++)
for (int j = 1; j <= i*i; j++)
for (int k = 1; k <= j*j; k++)
sum++;
printf("Sum = %d\n", sum);
return 0;
}
Затем вы используете существующий n ^ 3. n ^ 2 = n ^ 5? Это правильно?
Ответы
Ответ 1
Мы имеем i
и j < i*i
и k < j*j
, которые x^1 * x^2 * (x^2)^2 = x^3 * x^4 = x^7
по моему счету.
В частности, поскольку 1 < i < N
, мы имеем O (N) для цикла i
. Так как 1 < j <= i^2 <= N^2
, для второго цикла O (n ^ 2). Расширяя логику, мы имеем 1 < k <= j^2 <= (i^2)^2 <= N^4
для третьего цикла.
Внутренние к Outer циклам мы выполняем до N^4
раз для каждого цикла j
и до N^2
раз для каждого цикла i
и до N
раз в цикле i
, делая общее порядка порядка N^4 * N^2 * N = N^7
= O(N^7)
.
Ответ 2
Для i = 1
внутренний цикл запускает 1^1
раз, для внутреннего цикла i = 2
выполняется 2^2
times.... и для i = N
внутренний цикл запускает N^N
раз. Его сложность (1^1 + 2^2 + 3^3 + ...... + N^N
) порядка O(N^3)
.
Во втором случае для i = N
первая внутренняя петля выполняет итерацию N^N
раз, и, следовательно, вторая внутренняя петля (самая внутренняя) будет повторять до N * (N^N) * (N^N)
раз. Следовательно, сложность имеет порядок N * N^2 * N^4
, т.е. O(N^7)
.
Ответ 3
Я думаю, что на самом деле сложность - это O (n ^ 7).
Первый цикл выполняет N шагов.
Второй цикл выполняет N ^ 2 шага.
В третьем цикле j * j может достигать N ^ 4, поэтому имеет сложность O (N ^ 4).
В целом, N * N ^ 2 * N ^ 4 = O (N ^ 7)
Ответ 4
Да. В первом примере цикл i
запускает N
раз, а внутренний цикл j
настраивает i*i
раз, что составляет O(N^2)
. Итак, все это O(N^3)
.
Во втором примере существует дополнительный цикл O(N^4)
(loop to j*j
), поэтому он равен O(N^5)
.
Для более формального доказательства выясните, сколько раз sum++
выполняется в терминах N
, и посмотрите на самый высокий полиномиальный порядок N. В первом примере это будет a(N^3)+b(N^2)+c(N)+d
(для некоторых значений a
, b
, c
и d
), поэтому ответ равен 3.
NB: отредактированный пример 2, чтобы сказать это O (N ^ 4): неверно прочитать i*i
для j*j
.
Ответ 5
Рассмотрим количество вызовов всех циклов.
int main() {
int N = 8; /* for example */
int sum = 0;
for (int i = 1; i <= N; i++) /* Called N times */
for (int j = 1; j <= i*i; j++) /* Called N*N times for i=0..N times */
for (int k = 1; k <= j*j; k++) /* Called N^2*N^2 times for j=0..N^2 times and i=0..N times */
sum++;
printf("Sum = %d\n", sum);
return 0;
}
Таким образом, выражение sum ++ называется O (N ^ 4) * O (N ^ 2) * O (N) times = O (N ^ 7), и это общая сложность программы.
Ответ 6
Неправильный способ решить эту проблему (хотя часто и часто дает правильный ответ) заключается в том, чтобы приблизить среднее число итераций внутреннего цикла в худшем случае. Здесь внутренняя петля в худшем случае O (N ^ 4), средняя петля петлей в худшем случае O (N ^ 2) раз, а внешний цикл петли O (N) раз, давая (случайно) решение O ( N ^ 7), умножив их вместе.
Правильный путь - это работать изнутри, пытаясь быть явным в отношении того, что аппроксимируется.
Общее число итераций, Т, инструкции приращения совпадает с вашим кодом. Просто напишите:
T = sum(i=1..N)sum(j=1..i^2)sum(k=1..j^2)1.
Самая внутренняя сумма равна j ^ 2, давая:
T = sum(i=1..N)sum(j=1..i^2)j^2
Сумма, проиндексированная j, представляет собой сумму квадратов последовательных целых чисел. Мы можем вычислить, что именно: sum (j = 1..n) j ^ 2 есть n * (n + 1) * (2n + 1)/6. Полагая n = я ^ 2, получим
T = sum(i=1..N)i^2*(i^2+1)*(2i^2+1)/6
Мы могли бы продолжать вычислять точный ответ, используя формулу для сумм 6-й, 4-й и 2-й степеней последовательных целых чисел, но это боль, и для сложности мы заботимся только о наивысшей степени i. Таким образом, мы можем приблизиться.
T = sum(i=1..N)(i^6/3 + o(i^5))
Теперь мы можем использовать эту сумму (i = 1..N) я ^ p = Theta (N ^ {p + 1}), чтобы получить окончательный результат:
T = Theta(N^7)