【问题标题】:Asymptotic analysis of code fragment代码片段的渐近分析
【发布时间】:2010-12-05 15:12:06
【问题描述】:

我需要找到以下片段的大O运行时间:

sum =0; 
for (int i=1; i<n; i++) {
  for (int j=1; j< n/i; j++) {
    sum = sum +j;
  }
}

我知道外循环是 O(n),但我在分析内循环时遇到问题。我认为它是 O(log n)。

【问题讨论】:

    标签: big-o analysis


    【解决方案1】:

    正如 Dave 所说,它是 O(n log n),因为内部循环是 O(log n)。

    【讨论】:

    • 哇,真快;我回答的问题消失了:)
    【解决方案2】:

    让我们用这种伪数学风格来写吧。

    sum i <- [1..n] (sum j <- [1..n/i] 1)
    

    内循环(求和)需要

    n / i
    

    迭代,这使得整个术语

    sum i <- [1..n] (n/i)
    

    根据分配律化简和:

    n * (sum i <- [1..n] (1/i))
    

    内部和在很大程度上类似于1/x 上的积分,它是对数。

    所以O(n log n) 是对的。

    【讨论】:

      【解决方案3】:

      解决这个问题的最佳方法是考虑算法将采取多少步。

      如果你有 n 个元素,你就知道外层循环至少要运行 n 次。所以它必须至少是 O(n)。

      对于每个 i,内部循环必须运行多少次?它会随着 i 的增加而增加、保持不变还是减少?

      很明显,内循环的步数会随着 i 的增加而减少,更重要的是,它会非线性地减少。所以你知道它没有 O(n^2) 那么糟糕。

      所以它介于 O(n) 和 O(n^2) 之间......关于内部循环中的步骤如何减少的更多分析应该会让你到达那里。编辑:......虽然看起来人们已经放弃了它:)

      【讨论】:

      • 实际上,即使内部循环中的步数减少,它也可能是 O(n^2)(或更准确地说是 Theta(n^2))。例如,考虑内部循环为n-i 步骤的情况(在插入排序算法等中就是这种情况)。
      • for i in 1..n for j in 1..i ... 怎么样?根据你的解释,这不是as bad as O(n²),因为内部循环范围随着 i 的增加而减小,但它实际上是 O(n²)
      • @jk:有趣,只有 17 秒的差异^^
      • @Dario:你刚才不是在评论中反驳了你的回答吗?
      • @dario 和@jk - 你们是对的,我应该说“线性减少”。
      猜你喜欢
      • 2018-11-03
      • 1970-01-01
      • 2014-10-28
      • 2021-09-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-10-28
      相关资源
      最近更新 更多