【问题标题】:Complexity Analysis of the following loops以下循环的复杂性分析
【发布时间】:2019-09-15 01:22:15
【问题描述】:

我有一些双循环复杂度分析的练习,不知道自己做对了没有。

for i = 1 to n do 
    j = i
    while j < n do 
        j = 2∗j 
    end while 
end for

我对此的回答是O(n^2),因为第一个循环正在运行O(n) 次,而内部循环正在为外部循环的“最差”迭代进行O(n/2) 迭代。所以O(n) * O(n/2) = O(n^2)

再进一步看,我想我可以说内部循环正在做一个部分和,即O(n/2) + O(n-1) + ... + O(1),这也是O(n)


        for i = 1 to n do 
            j = n 
            while i∗i < j do 
                j = j − 1 
            end while 
        end for

再一次,外循环是O(n),而内循环在最坏的迭代中执行O(sqrt(n)),所以这里我认为是O(n*sqrt(n)),但我不确定这个。


       for i = 1 to n do 
            j = 2 
            while j < i do 
                j = j ∗j 
            end while 
        end for

这里的外循环是O(n),而内循环正在为最坏的情况工作O(logn)。因此我认为这是O(nlogn)


        i = 2 
        while (i∗i < n) and (n mod i != 0) do 
            i = i + 1 
        end while

最后,我不知道如何理解这一点。因为模数运算符。


我的问题是:

  1. 我在前 3 个示例中做错了吗?
  2. 我正在做的内部循环的“最坏情况方法”是否正确?
  3. 我应该如何处理最后一个练习?

【问题讨论】:

  • 是的,虽然最初是正确的。每个j 等于i * 2^x,因此您最多可以在内部循环中进行log2 n 迭代。复杂性不能比O(n log n) 最差。到底是不是更低,这是个问题。
  • 第二种情况很有趣,因为一旦i &gt;= sqrt(n),第二个循环就根本不会运行。对于i &lt; sqrt(n),它将执行n - i^2 迭代。这意味着像O(sqrt(n) * n + n - sqrt(n)) 这样的东西,我猜总共是O(n * sqrt(n))

标签: complexity-theory


【解决方案1】:

第一个问题:
内部循环需要log(n/i) 时间。上限为O(log(n)),总时间为O(n*log(n))。下限是log(n/2),并且仅对最后的n/2 项求和,总复杂度为n/2 * log(n/2) = n/2*log(n) - n/2 = O(n * log(n)),我们得到O(n* log(n)) 的界限很紧(我们有一个theta 界限)。

第二个问题:
内部循环需要n - i^2 时间(如果i^2 &gt;= n,则需要O(1))。请注意,对于i &gt;= sqrt(n),内部循环需要O(1) 时间,因此我们可以只为i in 1:sqrt(n) 运行外部循环并将O(n) 添加到结果中。内部循环的上限为n,总时间为O(n * sqrt(n) + n) = O(n ^ (3/2))。内部循环的下限是3/4 * n,仅对isqrt(n) / 2 求和(因此i^2 &lt; n / 4n - i ^ 2 &gt; 3/4 * n),我们得到Ω(sqrt(n) / 2 * n * 3/4 + n) = Ω(n^(3/2)) 的总时间,因此绑定@ 987654343@确实很紧。

第三个问题:
在这个j 从 2 开始,我们将它平方直到它到达i。在内循环的t 步骤之后,j 等于2^(2^t)。当j = 2 ^ (log(i)) = 2 ^ (2 ^ log(log(i))) 时,我们到达i,即在t = log(log(i)) 步骤之后。与前面的问题类似,我们可以再次给出上限和下限,并得到紧界O(n * log(log(n)))

第四个问题:
复杂性在2 = O(1)sqrt(n) 之间会有所不同,具体取决于n 的分解。在最坏的情况下,n 是一个完美的正方形,复杂度为O(sqrt(n)

最后回答您的问题:
1. 是的,你做错了一些事情。您在 1 和 3 中得出了错误的答案,在 2 中您的结果是正确的,但推理有缺陷;正如您在我的分析中看到的那样,内部循环不是O(sqrt(n))
2.考虑内部循环的“最坏情况”是好的,因为它给你一个上限(这在这类问题中大部分是准确的),但要建立一个紧密的界限,你还必须显示一个下限,通常是就像我在一些例子中所做的那样,只取较高的术语并将它们降低到第一个。另一种证明紧密界限的方法是使用已知系列的公式,例如1 + ... + n = n * (n + 1) / 2,给出O(n^2) 的直接界限,而不是通过1 + ... + n &gt;= n/2 + ... + n &gt;= n/2 + ... + n/2 = n/2 * n/2 = n^/4 = Ω(n^2) 获得下限。
3. 以上回答。

【讨论】:

  • 您能否解释一下为什么在第三种情况下 j 等于 2^(2^t) 而不是 2^t ?
  • 你从 2=2^(2^0) 开始。如果j2^(2^t),我们将它平方,我们将得到j = (2^(2^t))^2 = 2^((2^t) * 2) = 2^(2^(t+1))。因此在t 步骤我们有j = 2^(2^t)
【解决方案2】:

对于内部循环中的第一个,我们有: i, 2*i, 4*i, ... , (2^k)*i 其中(2^k)*i &lt; n。所以k &lt; logn - logi。如您所说,外循环重复n+1 次。我们总共有这个总和:

等于

因此我认为复杂度应该是O(nlogn)


我们有第二个:


第三个:

所以我觉得应该是O(log(n!))


对于最后一个,如果n 是偶数,它将是O(1),因为我们没有进入循环。但最坏的情况是当n是奇数并且不能被任何平方数整除时,那么我认为应该是

【讨论】:

  • 我认为第二个会少很多。您必须将1... n 间隔拆分为sqrt(n),因为任何i &gt; sqrt(n) 根本不会运行内部循环。 O(n^2) 显然太过分了。
  • 是的,从sqrt(n) 向前,内部循环不运行。计算出的最后一句是n - (sqrt(n))^2,即i = sqrt(n),后面的将被忽略。
  • 但是,您最后的声明 n^2 - (n^3/2) 不能仅仅简化为 O(n^2)
  • 它是O(n^2 - n^(1.5)),我认为可以简化为O(n^2)。但O(n^2 - n^(1.5)) 更准确。
  • 不,它可以进一步简化为n * (1 - sqrt(n)),看起来比n^2要小得多。在我看来O(n * sqrt(n)) 将被认为是正确的答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多