【问题标题】:Why does nested loop with list.add gives O(n^4) time complexity?为什么带有 list.add 的嵌套循环会给出 O(n^4) 时间复杂度?
【发布时间】:2018-08-18 12:32:11
【问题描述】:

我遇到了这个代码 sn-p 的大 O 时间复杂度的问题: 保证以下代码的时间复杂度为O(n^4)。

ArrayList<Integer> list = new ArrayList<Integer>();

for(int i = n; i>=1; i--)           //n 
    for(int j = 1; j<=i; j++)       //n     
        if(!list.contains(i*j))     //n?    
            list.add(i*j);          //1?

我的问题:为什么是 O(n^4) 而不是 O(n^3)?

【问题讨论】:

  • n 初始化为什么?
  • @JanusVarmarken 这是完整的问题。 n 是什么来确定大 O 无关紧要...您可以假设它是大于 1 的某个数字。
  • 我怀疑这可能是由于 add 造成的,因为 arraylist 由数组支持,该数组在填充时会加倍,并且所有元素都必须复制到新数组中。
  • 但是,这只会在 n 上添加另一个常量(因为 if 不是 loopingadd 周围)。

标签: java time-complexity big-o


【解决方案1】:

list 大约有 n^2/2 条目[*],因此查找 list.contains(i*j)O(n^2) 而不是 O(n)

*:少了一些,因为没有添加重复项,但我想足以算作n^2

【讨论】:

  • list.contains(i*j) 在这里如何给出 O(n^2)?介意详细说明吗?
  • 忽略重复;最后,您将在列表中添加 (n^2)/2 条目。 containsO(r) 其中r 是列表中的条目数,因此O(n^2/2) = O(n^2)
  • 很好的观察!
  • @k5_ 如果有 3 层嵌套 for 循环,都循环 n 次,在这种情况下,.contains() 将是 O(n^3) ?这意味着整体复杂度变为 O(n^6) ?这是正确的理解吗?
【解决方案2】:

list.contains(i*j) 发生在 O(n^2) 中,因为 i 和 j 取决于 n(如果使用线性搜索)。基本上它将是嵌套循环中的 2 个 O(n) 循环和嵌套循环内 O(n^2) 的操作,因此 O(n^4)

【讨论】:

  • i*j 只是一个整数,所以它将是 list.contains(x) 其中x = i*j。所以它应该只是线性的,O(n) 查找时间。
  • @Bill 在这种情况下的复杂性取决于列表中的条目数,而不是参数值。
  • @Bill 就 x 而言,即 i*j 它是线性的,但就 n 而言它是二次的。
  • @k5_,这是我评论的重点。它应该只是线性查找,因为参数无关紧要。
  • @k5_,呵呵!当然。我的电线交叉了。 O(n^2) 在这种情况下,因为列表将包含 n^2 元素,最坏的情况。对不起,我的困惑。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-04-06
  • 1970-01-01
  • 2018-01-14
  • 2015-05-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多