运行 嵌套循环的时间
Running Time of Nested Loops
我确定这个嵌套循环的 运行 时间是 O(N*log(N))。 运行内层循环的时间是log(N),外层循环是N。
for (int i = 0; i < N; ++i) {
for (int j = 1; j <= i; j *= 2) {
}
}
在内部循环中,如果我将 j *= 2
更改为 j *= 3
会怎样?在这种情况下,结果将如何变化?
它仍然是对数的。但是,它将按常数因子进行缩放(这与 Big O 分析无关)。
效果是对数的底发生变化(参见https://en.wikipedia.org/wiki/Logarithm#Change_of_base)。
---------[j = 2 * j] 对于 j < i:------------
j = 2*1 = 2 =>2^1
2*2 = 4 =>2^2
2*4 = 8 =>2^3
............. 2^k = n say n==i
if log applied on both side 2^k = n
log(2^k) = logn
k = log_2(N) where 2 is the base
---------[j = 3 * j] 对于 j < i:------------
j = 3*1 = 3 =>3^1
3*3 = 9 =>3^2
3*9 = 27 =>2^3
.............loop stop when 3^k = n say n==i
if log applied on both side 3^k = n
log(3^k) = logn
k = log_3(N) where 3 is the base
@Kevin 完全正确,但我想我会展示一些实验结果。您可以通过创建一个计数器来轻松地对此进行测试,该计数器在每个内部循环迭代中递增,并且 运行 用于不同的 N 值。然后可以采用 time = a * N * log(N)
的形式进行拟合。对于 j *= 2
的情况,我们得到一个系数 a = 1.28
。对于 j *= 3
,我们得到 a = 0.839
。
我使用下面的 MATLAB 脚本生成了这张图:
clear
clc
close all
nmin = 10;
nmax = 1000;
count1 = zeros(nmax - nmin + 1, 1);
for n = nmin: nmax
k = 0;
for i = 0: n - 1
j = 1;
while (j <= i)
j = j * 2;
k = k + 1;
end
end
count1(n - nmin + 1) = k;
end
ns = (nmin: nmax)';
figure
hold on
plot(ns, count1, '--')
a1 = mean(count1 ./ (ns .* log(ns)))
fit1 = a1 * ns .* log(ns);
plot(ns, fit1)
%%
count2 = zeros(nmax - nmin + 1, 1);
for n = nmin: nmax
k = 0;
for i = 0: n - 1
j = 1;
while (j <= i)
j = j * 3;
k = k + 1;
end
end
count2(n - nmin + 1) = k;
end
ns = (nmin: nmax)';
plot(ns, count2, '-.')
a2 = mean(count2 ./ (ns .* log(ns)))
fit2 = a2 * ns .* log(ns);
plot(ns, fit2)
xlabel('N')
ylabel('Time complexity')
legend('j *= 2', 'j *= 2 fit', 'j *= 3', 'j *= 3 fit', 'Location', 'NorthWest')
如果您熟悉数学公式并且对更严格的精度感兴趣,您可以有条不紊地使用 Sigma 表示法,如下所示:
来自我的 blog:
我确定这个嵌套循环的 运行 时间是 O(N*log(N))。 运行内层循环的时间是log(N),外层循环是N。
for (int i = 0; i < N; ++i) {
for (int j = 1; j <= i; j *= 2) {
}
}
在内部循环中,如果我将 j *= 2
更改为 j *= 3
会怎样?在这种情况下,结果将如何变化?
它仍然是对数的。但是,它将按常数因子进行缩放(这与 Big O 分析无关)。
效果是对数的底发生变化(参见https://en.wikipedia.org/wiki/Logarithm#Change_of_base)。
---------[j = 2 * j] 对于 j < i:------------
j = 2*1 = 2 =>2^1
2*2 = 4 =>2^2
2*4 = 8 =>2^3
............. 2^k = n say n==i
if log applied on both side 2^k = n
log(2^k) = logn
k = log_2(N) where 2 is the base
---------[j = 3 * j] 对于 j < i:------------
j = 3*1 = 3 =>3^1
3*3 = 9 =>3^2
3*9 = 27 =>2^3
.............loop stop when 3^k = n say n==i
if log applied on both side 3^k = n
log(3^k) = logn
k = log_3(N) where 3 is the base
@Kevin 完全正确,但我想我会展示一些实验结果。您可以通过创建一个计数器来轻松地对此进行测试,该计数器在每个内部循环迭代中递增,并且 运行 用于不同的 N 值。然后可以采用 time = a * N * log(N)
的形式进行拟合。对于 j *= 2
的情况,我们得到一个系数 a = 1.28
。对于 j *= 3
,我们得到 a = 0.839
。
我使用下面的 MATLAB 脚本生成了这张图:
clear
clc
close all
nmin = 10;
nmax = 1000;
count1 = zeros(nmax - nmin + 1, 1);
for n = nmin: nmax
k = 0;
for i = 0: n - 1
j = 1;
while (j <= i)
j = j * 2;
k = k + 1;
end
end
count1(n - nmin + 1) = k;
end
ns = (nmin: nmax)';
figure
hold on
plot(ns, count1, '--')
a1 = mean(count1 ./ (ns .* log(ns)))
fit1 = a1 * ns .* log(ns);
plot(ns, fit1)
%%
count2 = zeros(nmax - nmin + 1, 1);
for n = nmin: nmax
k = 0;
for i = 0: n - 1
j = 1;
while (j <= i)
j = j * 3;
k = k + 1;
end
end
count2(n - nmin + 1) = k;
end
ns = (nmin: nmax)';
plot(ns, count2, '-.')
a2 = mean(count2 ./ (ns .* log(ns)))
fit2 = a2 * ns .* log(ns);
plot(ns, fit2)
xlabel('N')
ylabel('Time complexity')
legend('j *= 2', 'j *= 2 fit', 'j *= 3', 'j *= 3 fit', 'Location', 'NorthWest')
如果您熟悉数学公式并且对更严格的精度感兴趣,您可以有条不紊地使用 Sigma 表示法,如下所示:
来自我的 blog: