虽然@alestanis提供什么样子对我来说,这个问题比那些评论的多少更准确的分析,我仍然不认为这是完全正确的。
让我们创建一个打印出由内循环产生i
值的小测试程序:
#include <iostream>
void inner(double k) {
double i;
i = 0.0;
while(i < k) {
i ++;
i = i * i;
std::cout << i << "\n";
}
}
int main() {
inner(1e200);
return 0;
}
当我运行它,结果我得到的是:
1
4
25
676
458329
2.10066e+011
4.41279e+022
1.94727e+045
3.79186e+090
1.43782e+181
1.#INF
如果迭代次数是对数的,那么达到特定数字的迭代次数应该与限制中的位数成正比。例如,如果它是对数的,则应该花费大约180次迭代才能达到1e181,给出或采取一些(相当小的)恒定因子。这显然不是这种情况 - 通过用科学计数法查看结果的指数可以很容易地看出,这大约是每次迭代的数字数量的两倍,其中对数表示每次迭代大致增加一位数字。
我不是绝对的确定,但我相信把内部循环放在类似O(log log N)而不是O(log N)的东西上。我认为可以很容易地认同外部循环可能是O(N)(尽管它目前只写入一次),总体复杂度为O(N log log N)
。
我觉得有必要补充一点,从实用的角度来看,O(log log N)
通常可以被视为基本常量 - 如上所示,只有11次迭代才能达到您可以用一个典型双精度浮点数指定的最高限制。因此,对于大多数实际目的而言,整体复杂度可以被视为O(N)
。
[糟糕 - 没有注意到他在我写这篇文章时已经回答了,但是看起来@ jwpat7已经达到了我所做的相同的结论。对他/她的称赞。]
'k = n + 2'不应该是:'k = k + 2'还是类似的东西?现在你的外层循环不会迭代多次。 – Joost
我估计时间复杂度仍然停留在O(n * m)。内部循环是O(m),外部循环,就像你提到的那样,是O(n/2)。总结它是O(n * m)/ 2。 2是一个常数,随着投入量的增加,它将与比率无关。我正在学习自己。所以,我可能是错的。 –
您可能对[此问题]感兴趣(http://cs.stackexchange.com/questions/4800/the-order-of-growth-analysis-of-simple-for-loop)[cs.se]和这些问题与Raphael的评论有关。 – Gilles