【问题标题】:Time complexity of loop multiplying the value by two or three将值乘以二或三的循环时间复杂度
【发布时间】:2014-06-05 14:04:39
【问题描述】:
我在一个 SO 问题中找到了以下 for 循环。
我发现时间复杂度是O(n log n)。
如果我们将k *= 2 更改为k *= 3,我将如何计算时间复杂度?
// 'int n' is defined somewhere
int var = 0;
for (int k = 1; k <= n; k *= 2)
for (int j = 1; j <= n; j++)
var++;
【问题讨论】:
标签:
c++
algorithm
time-complexity
【解决方案1】:
时间复杂度仍为O(n log n)。
对于k *= 2,log 将以 2 为基数。
对于k *= 3,log 将以 3 为基数。
但是log 的基数的变化只会通过一个常数因子影响结果(这可以从log<sub>b</sub>a = log<sub>c</sub>a / log<sub>c</sub>b,对于任何基数c 的事实得出),这在 big -O 表示法,因此它们具有相同的时间复杂度。
我们从哪里得到log<sub>2</sub>n?
嗯,k 的值是这样的:
1, 2, 4, 8, 16, ..., 2m for some m, where 2m <= n < 2m+1
= 20 + 21 + 22 + ... + 2m
当然上面只有m+1(0 到m)术语,所以循环运行m+1 次。
现在如果我们可以使用一些基本的对数来得到m 的n:
2m = c.n for some constant c, where 1 <= c < 2
log22m = log2(c.n)
m log22 = log2(c.n)
m.1 = log2c + log2n
m = O(log2c + log2n)
= O(log2n) // constant terms can be ignored
我们也可以对k *= 3 采用与上述完全相同的方法,只需将2 替换为3。
【解决方案2】:
答案是N×log3N。
要知道为什么,你需要弄清楚为什么原始问题的答案是 N×log2N。它会执行多少次(我们称之为k)?它将根据需要执行多次,以将2 与自身相乘,这样结果就会超过N。也就是说,2k > N。现在对表达式两边都取对数(对数的定义可以看here),看到k > log2N.
我们之所以使用2 作为对数的底,是因为左边指数的底是2。很容易看出,如果 exponen 的基数是 3,则应用 log3 会得出您正在解决的问题的答案。
【解决方案3】:
您可以使用 Sigma 符号正式且有条不紊地进行:
查看此document 的最后一张幻灯片。