【问题标题】:What is the order of growth of the worst case running time of the following code fragment as a function of N?作为 N 的函数,以下代码片段的最坏情况运行时间的增长顺序是多少?
【发布时间】:2014-09-07 04:34:37
【问题描述】:
int sum = 0;
for (int i = 1; i <= N; i = i*2)
    for (int j = 1; j <= N; j = j*2)
        for (int k = 1; k <= j; k++)
            sum++;

根据解决方案是 NlogN。但是,我认为这只是 logN。 i for 循环迭代 logN 次,因为每次迭代 i 加倍。 j for 循环与i for 循环相同,因此它也会迭代 logN 次。最后是k for 循环,因为它被设置为小于或等于j,它将迭代j 的相同次数,因此,我们还有另一个logN 迭代。将三者相乘,我们得到 logN * logN * logN 总迭代次数或 (logN)^3 的复杂度。为什么我的思维过程不正确?

【问题讨论】:

    标签: big-o complexity-theory


    【解决方案1】:
    sum++;
    

    这显然是 O(1)

    for (int k = 1; k <= j; k++)
        sum++;
    

    循环运行j 次,所以是O(j)

    for (int j = 1; j <= N; j = j*2)
        for (int k = 1; k <= j; k++)
            sum++;
    

    所以这变得很棘手。我们知道内循环是O(j),但j 在外循环中正在发生变化。你说:

    最后是k for循环,因为设置为小于等于j,所以会迭代j的次数相同

    没有。 j 循环按双打计数。但是内部循环是按增量计算的。他们不会进行相同数量的迭代。

    由于每个内部循环在 O(j) 时间内运行,我们只需对循环中的每个时间求和 j。 j 每次翻倍,这样就给了我们:

    1 + 2 + 4 + 8 + 16 + ... + n
    

    这个序列最终会略小于 2n。 (为什么留给读者作为excersize。)因此它的O(n)

    for (int i = 1; i <= N; i = i*2)
        for (int j = 1; j <= N; j = j*2)
            for (int k = 1; k <= j; k++)
                sum++;
    

    外部循环不与内部循环交互,并运行log(N) 次给我们O(N log N)

    【讨论】:

    • 您是如何立即知道将每个循环的运行时间相加得出1 + 2 + 4 + 8 + 16 + ... + n?是因为您从经验中知道,还是有一种快速的方法可以解决这个问题?
    • @JustinLiang,内部循环运行j 次。 j是1,第一次,2第二次,4第三次等等。我只是按照程序的逻辑。
    • 对,但是 j 循环不是运行 logN 次吗? i 循环也是如此。所以我们应该有 N log^2(N)?
    • @JustinLiang,问题是k 循环。在某些情况下它运行一次,而在其他情况下运行N 次。结果平均运行 O(N / log N) 次。所以你不能逃脱只是将N 乘以它。您必须考虑到j 正在发生变化。
    【解决方案2】:

    使用 Sigma 表示法,您最终可能会有条不紊地得到精确的公式:

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-12-13
      • 1970-01-01
      • 2014-06-12
      • 2020-08-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多