【问题标题】:Why does this loop return a value that's O(n log log n) and not O(n log n)?为什么这个循环返回一个 O(n log log n) 而不是 O(n log n) 的值?
【发布时间】:2015-08-28 22:15:41
【问题描述】:

考虑以下 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 的答案是错误的?

【问题讨论】:

    标签: loops for-loop time-complexity nested-loops asymptotic-complexity


    【解决方案1】:

    答案是 (D) O(n * log(log n))。原因如下:-

    第一个 for 循环包含另外 2 个分别基于 j 和 k 值的 for 循环。此外,j 从 n 减半,直到大于 1。因此,p 将等于最大整数(log n)。并且,k 加倍直到等于 p --- 其中 p 已从前一个循环中设置并且将等于 [log n],其中 [x] 等于 x 的最大整数。

    因此,第三个循环将运行 log (log n) 时间,因此 q 的值将是 log (log n)。因此,两个内部循环都是运行 n 次的外部 for 循环的一部分。

    q的近似值 = n* log (log n)) = O(n log(log n))。

    【讨论】:

    • 仔细阅读这个问题 - 它询问的是返回值 是什么,而不是运行时。我第一次犯了同样的错误。
    • @templatetypedef-添加了答案,但是,可能我为时已晚。 :(
    • 这是为了帮助我:)
    • @coder101-哦,我认为 templatetypedef 赞成。无论如何,谢谢。 :)
    • 哥们你能不能也检查一下这个问题:) stackoverflow.com/questions/30811753/…
    【解决方案2】:

    我在这里看到的唯一错误是关于第二个循环: 对于 (j=n; j>1; j=j/2) 你在 cmets 中说:这个循环运行 Θ(Log Log n) 时间

    在我看来,这个循环运行 O(Log n) 次

    第一个和第三个循环的运行时间是正确的(O(n) 和 O(Log Log n))。

    编辑:我同意前面的回答。我没有注意到问题是关于返回值,而不是运行时间!

    【讨论】:

    【解决方案3】:

    这个问题很棘手——代码的运行时返回值是有区别的。

    第一个循环的运行时间确实是 O(log n),而不是 O(log log n)。我在这里转载了:

    p = 0;
    for (j=n; j > 1; j=j/2)
      ++p;
    

    在每次迭代中,j 的值都会下降两倍。这意味着该循环终止所需的步数由 k 的最小值给出,使得 n / 2k ≤ 1。求解,我们看到 k = O(log 2 n).

    请注意,此循环的每次迭代都会将 p 的值增加一。这意味着在循环结束时,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)

    希望这会有所帮助!

    【讨论】:

    • @coder101 据我所知,时间复杂度为 O(n log log n) 的说法是不正确的。请注意,该问题不是询问函数需要多长时间才能返回,而是询问您可以对返回值 (q) 说些什么。
    • 是的,这很有帮助,他们的回答是正确的,但解释是错误的 :)
    • 哥们你能不能也检查一下这个问题:) stackoverflow.com/questions/30811753/…
    猜你喜欢
    • 1970-01-01
    • 2011-12-12
    • 2011-12-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-24
    • 1970-01-01
    • 2012-05-09
    相关资源
    最近更新 更多