考虑以下C函数:
int fun1 (int n)
{
int i, j, k, p, q = 0;
for (i = 1; i<n; ++i)
{
p = 0;
for (j=n; j>1; j=j/2)
++p;
for (k=1; k<p; k=k*2)
++q;
}
return q;
}
问题是要确定以下哪一项最接近函数fun1
的返回值?
(A)n ^ 3
(B)n(logn)^ 2
(C)nlogn
(D)nlog(logn)
这是给出的解释:
int fun1 (int n)
{
int i, j, k, p, q = 0;
// This loop runs T(n) time
for (i = 1; i < n; ++i)
{
p = 0;
// This loop runs T(Log Log n) time
for (j=n; j > 1; j=j/2)
++p;
// This loop runs T(Log Log n) time
for (k=1; k < p; k=k*2)
++q;
}
return q;
}
但是,如果将循环变量除以/乘以常量,则循环的时间复杂度被视为O(Logn)。
for (int i = 1; i <=n; i *= c) {
// some O(1) expressions
}
for (int i = n; i > 0; i /= c) {
// some O(1) expressions
}
但是有人提到内部循环每个都需要Θ(Log Log n)时间,任何人都可以解释一下ar是错误的原因吗?
答案 0 :(得分:4)
这个问题很棘手 - 代码的运行时和返回值之间存在差异。
第一个循环的运行时确实是O(log n),而不是O(log log n)。我在这里重印了它:
p = 0;
for (j=n; j > 1; j=j/2)
++p;
在每次迭代中,j的值下降两倍。这意味着该循环终止所需的步数由k的最小值给出,使得n / 2 k ≤1。求解,我们看到k = O(log 2 n)。
请注意,此循环的每次迭代都会将p的值增加1。这意味着在循环结束时,p的值是Θ(log n)。因此,下一个循环确实在时间O(log log n)中运行:
表示(k = 1; k
原因在于,使用与前一节类似的推理,此循环的运行时间为Θ(log p),并且由于p =Θ(log n),因此最终为Θ(log log n)
然而,问题是不询问运行时是什么。它询问返回值是什么。在每次迭代中,q的值(最终返回的值)增加Θ(log log n),因为它在时间Θ(log log n)中运行的循环的每次迭代增加一次。这意味着q的净值是Θ(n log log n)。因此,虽然算法在时间O(n log n)中运行,但返回的值为O(n log log n)。
希望这有帮助!
答案 1 :(得分:1)
答案是(D)O(n * log(log n))。原因如下所述: -
第一个for循环包含其他2个for循环,它们分别基于j和k的值。此外,j从n减半,直到它大于1.因此,p将等于最大整数(log n)。并且,k加倍,直到它等于p ---其中p已经从前一个循环设置并且将等于[log n],其中[x]等于x的最大整数。
因此,第三个循环将运行log(log n)时间,因此q的值将为log (log n)
。因此,内部循环都是外部for循环的一部分,运行n次。
q = n * log(log n)的近似值= O(n log(log n))。
答案 2 :(得分:1)
我在这里看到的唯一错误涉及第二个循环: for(j = n; j&gt; 1; j = j / 2) 你在评论中说:这个循环运行Θ(Log Log n)时间
在我看来,这个循环运行O(Log n)次
第一个和第三个循环的运行时间是正确的(O(n)和O(Log Log n))。
编辑:我同意之前的回答。我没有注意到问题是关于返回值,而不是运行时间!