【问题标题】:Nested loops with dependent variables具有因变量的嵌套循环
【发布时间】:2016-07-26 21:42:23
【问题描述】:

假设我们有以下循环:

for (int i = 0; i < n; i++)
   for (int j = i+1; j < n; j++)
      for (int k = j+1; k < n; k++)
         for (int l = 0; l < n; l++)

我知道第一个循环会循环 n 次。

我认为第二个将运行 (1/2) * (n^2 + n - 2) 次,因为我们需要计算从 2 到n,不是从 1 到 n。

但是,我不知道第三个和第四个。

【问题讨论】:

    标签: algorithm loops for-loop iteration


    【解决方案1】:

    有(至少)两种方法可以理解时间复杂度:第一种方法是注意三个嵌套的 for 循环恰好生成 n-set 的所有 3-subsets,第二种方法是“直接”方法。

    组合论证

    前三个 for 循环恰好选择了 n-set 的所有 3-subset,每个 3-subset 只选择一次(想想看)。有(n choose 3) = O(n^3) 这样的子集(参见here)。最里面的循环为其他三个循环的每个O(n^3) 迭代执行O(n) 工作,因此总时间为O(n^4)。

    三个循环(没有最里面的一个)正好进行n choose 3 = n!/(3!(n-3)!) 迭代。这正是n*(n-1)*(n-2) / 6 迭代。

    直接论证

    不管其他循环如何,最里面的循环都会执行n次,因此时间复杂度将为O(n * f(n)),其中f(n)是其他三个循环的时间复杂度,如果我们删除最里面的循环。

    两个最里面的循环(j- 和 k-indexed 的循环)一起花费O(i^2) 时间。这很容易看出——它与从j=0 到i-1 和k=j 到i-1 的双循环相同,所以时间是O(1) + O(2) + ... + O(i) = O(i^2)。

    因为最外层循环从i=0 到n-1,所以总复杂度为n * (O(1^2) + O(2^2) + ... + O(n^2)),即O(n * n^3):最外层循环(i-indexed)执行双for循环(@987654350 @- 和 k-indexed) 从 i=0 到 i=n-1。

    因此我们有O(n^4) 的总运行时间。

    要获得准确的迭代次数,您必须计算合适的i 的项i*(i-1)/2 = (i^2-i)/2 的总和。让我们只求和,最后除以 2。

    你可以把它分成两个总和,

    (1^2 + 2^2 + ...n-1) - (1 + 2 + ... + n-1) =
    = n(n-1)(2n-1)/6 - n*(n-1)/2 =
    = n*(n-1)(n-2)/3
    

    现在我们除以二得到结果n*(n-1)*(n-2)/6。和上面的完全一样。 (见how to compute the sum of first n squares。)

    【讨论】:

    • 好的,我了解运行时间复杂度,但嵌套循环的确切迭代次数是多少?
    • 正是n choose 3。这是n! / (3!*(n-3)!),或者简化为n*(n-1)*(n-2)/6。
    【解决方案2】:

    第一个循环将重复 n 次,第二个循环将执行 (n-1) 次,第三个循环将循环 (n-2) 次,最后一个循环将执行 l 次。最后他们都会去 n*(n-1)*(n-2)*l 次。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-08-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-11-14
      • 2018-12-25
      相关资源
      最近更新 更多