1) i=s=1;
while(s<=n)
{
i++;
s=s+i;
}
2) for(int i=1;i<=n;i++)
for(int j=1;j<=n;j+=i)
cout<<"*";
3) j=1;
for(int i=1;i<=n;i++)
for(j=j*i;j<=n;j=j+i)
cout<<"*";
有人可以解释这三个代码的时间复杂度吗? 我知道答案,但我无法理解它是怎么来的
答案 0 :(得分:0)
1)为了解决这个问题,我们需要弄清楚s
'循环迭代中x
的大小。然后我们将知道在达到条件s > n
之前会发生多少次迭代。
在x
'次迭代中,变量i
的值为x + 1
并且变量s
的值等于所有先前值的i
之和。因此,在该迭代中,s
的值等于
sum_{y = 1 .. x} (y+1) = O(x^2)
这意味着我们在s = n
次迭代中有x = O(\sqrt{n})
次。这就是循环的运行时间。
如果您不确定为什么总和是O(x^2)
,我会在here之后给出这样的另一个问题的答案,并采用相同的技巧。在这种特殊情况下,您还可以使用身份
sum_{y = 1 .. x} y = y choose 2 = (y+1)(y) / 2
这种身份可以通过y
上的归纳轻松证明。
2)尝试分析内部循环的运行时间,作为i
和n
的函数。由于我们从一开始,以n
结束,并按i
计算,因此它会运行n/i
次。所以外循环的总时间是
sum_{i = 1 .. n} n/i = n * sum_{i = 1 .. n} 1 / i = O(n log n)
系列sum_{i = 1 .. n} 1 / i
称为谐波系列。众所周知,它收敛于O(log n)
。我不能在这里附上一个简单的证据。虽然可以用微积分来证明。这是一个你必须知道的系列。如果你想看一个简单的证明,你可以在“比较测试”上查看维基百科。那里的证明只显示系列是&gt; = log n,但是同样的技术可以用来表示它也是<= O(log n)
。
3。)这看起来像是一个棘手的问题。内部循环将运行一次,但是一旦它以j = n + 1
退出,我们就永远不会重新进入此循环,因为没有后续行会再次生成j <= n
。我们将多次运行j = j * i
,其中i
为正数。因此,j
最终将至少与n!
一样大。对于n
的任何重要值,这将导致溢出。忽略这种可能性,代码将总共执行O(n)
次操作。