for(i=1;i<=n;i=pow(2,i)) { print i }
时间的复杂度是多少?
值kth
的近似i
项将是pow(2,(pow(2,pow(2,pow(2, pow(2,pow(2,...... k times)))))))
如何将kth value of i < n
的上述值k
求解。
答案 0 :(得分:2)
您所拥有的与tetration(2,n)类似,但是由于您输入了错误的结束条件而没有。
复杂度在很大程度上取决于域和实现。从您的示例代码中,我推断出真实域和整数。
此函数的增长非常快,因此经过5次迭代后,您需要bigints,即使+,-,*,/,<<,>>
也不是O(1)
。 pow和print的实施也有很大的影响。
如果n<tetration(2,4)
小,则可以假设复杂度为O(1)
,因为对于这样小的n,没有渐近线可言。
请注意,pow
在大多数语言中都是浮点,并且可以将2 by i
的强大功能转换为简单的位移,所以我们假设:
for (i=1;i<=n;i=1<<i) print(i);
我们可以使用i
的先前状态来计算1<<i
,如下所示:
i0=i; i<<=(i-i0);
但是在这么大的数字上并没有加速。
现在,十年print(i)
的复杂性是以下之一:
O( log(i)) // power of 10 datawords (like 1000000000 for 32 bit)
O((log(i))^2) // power of 2 datawords naive print implementation
O( log(i).log(log(i))) // power of 2 datawords subdivision or FFT based print implementation
移位1<<i
和比较i<=n
的复杂度是:
O(log(i)) // power of 2 datawords
因此,以2个数据字的幂为print
选择最佳实现会导致迭代:
O( log(i).log(log(i) + log(i) + log(i) ) -> O(log(i).log(log(i)))
乍一看,人们会认为我们需要知道k
的迭代次数n
:
n = tetration(2,k)
k = slog2(n)
或Knuth's notation与Ackermann function直接相关:
n = 2↑↑k
k = 2↓↓n
但是,与循环内部内容的内部复杂度相比,迭代次数非常少,下一次迭代增长得如此之快,以至于上一次迭代可以忽略下一次迭代的一部分,因此我们可以忽略它们,而只考虑最后一个/迭代...
所有这些假设之后,我得到了最终的复杂性:
O(log(n).log(log(n)))
答案 1 :(得分:0)
在每次迭代中,您的幂为std::string
。
让log ^ {k}(n)是对n应用k次的对数函数。例如,log ^ {1}(n)= log(n),而log ^ {2}(n)= log(log(n))。
在此表示法下,您的算法的运行时间为log ^ {k}(n)。