【问题标题】:Finding complexity of recursive algorithm?寻找递归算法的复杂性?
【发布时间】:2014-01-30 18:59:23
【问题描述】:

我无法找到递归方法的复杂性。我有一个算法可以按升序对数组的元素进行排序。基本上我所做的就是写下算法中的每个步骤以及最佳/最坏情况的执行次数,然后将每个情况的总和计算出来,然后找到 Big-O/Big-Omega。但我不确定递归调用?我是否记下它在方法内被调用的次数,或者它被调用的总次数(可能会有所不同)?

所以假设我有一个数组 A = [5, 4, 3, 2, 1](如果我没记错的话,这将是最坏的情况),那么我首先会遍历数组while 循环(参见下面的算法),然后在第二个 while 循环中再次向后,然后是递归调用。总的来说,我调用了我的方法一次(原始调用),然后是第二次,然后是第三次(没有进入 if 语句)。所以这是 n = 5 个元素的数组的 3 倍。但是在方法本身内部,递归调用发生了一次。我很混乱! :S

另外,时间复杂度和空间复杂度有什么区别?任何提示/建议都会有所帮助。

谢谢!

这是给定的算法:

Algorithm MyAlgorithm(A, n) 
    Input: Array of integer containing n elements 
    Output: Possibly modified Array A 
        done ← true 
        j ← 0 
        while j ≤ n - 2 do 
            if A[j] > A[j + 1] then 
                swap(A[j], A[j + 1]) 
                done:= false 
            j ← j + 1 
        end while 
        j ← n - 1 
        while j ≥ 1 do 
            if A[j] < A[j - 1] then 
                swap(A[j - 1], A[j]) 
                done:= false 
            j ← j - 1 
        end while 
        if ¬ done 
            MyAlgorithm(A, n) 
        else 
           return A

这是我的解决方案:

Statement                Worst Case         Best Case
------------------------------------------------------------------
done = true                  1                  1
j = 0                        1                  1
j <= n-2                     n                  n
A[j] > A[j+1]                n-1                n-1
swap(A[j], A[j+1])           n-1                0
done = false                 n-1                0
j = j + 1                    n-1                n-1
j = n - 1                    1                  1
j >= 1                       n-1                n-1
A[j] < A[j-1]                n-1                n-1
swap(A[j-1], A[j])           n-1                0
done = false                 n-1                0
j = j - 1                    n-1                n-1
if ¬done                     1                  1
MyAlgorithm(A, n)            1                  0
return A                     1                  1
------------------------------------------------------------------
Total:                       10n-2                6n
Complexity:                  f(n) is O(n)         f(n) is Omega(n)

这也是我在 stackoverflow 上的第一篇帖子,所以我不确定我是否正确发布了这些帖子。

【问题讨论】:

  • 您的算法,如所写,并没有说明在递归调用之前以何种方式对A 进行排序变得更简单。您的分析(或算法)错误的一个重要线索是,您已确定您的基于比较的排序在最坏情况 O(n) 时间内运行,这可能是错误的。
  • MyAlgorithm(A, n) = O(1) 绝对是错误的。此外,您还没有证明您检查的输入系列(降序排序的序列)实际上是最坏的情况。
  • 算法给的,不是我自己写的。。还有,Niklas,我没有写O(1),我找到了O(n)
  • 在 SO 上发布问题的一种错误方法是将 URGENT 放在标题中。
  • 顺便说一下,递归冒泡排序是个坏主意,如果你的语言没有针对尾递归进行优化,那么任何大小合适的数组都会出现堆栈溢出(如果不是这样的话只是伪代码)

标签: algorithm recursion complexity-theory big-o


【解决方案1】:

看起来这个算法是冒泡排序的某种变体。假设它工作正常,它的性能应该是O(n^2)

要分析性能,你应该注意到过程体(没有递归)占用O(n),所以算法占用的总时间是O(R n),其中R是循环的次数递归在完成之前被调用。由于每个冒泡通道应该在最终的排序位置留下至少一个元素,R&lt;=n/2,因此整个算法是 O(n^2) 最坏的情况。

不幸的是,在您的算法中使用递归的方式对于确定其性能并不是特别有用:您可以轻松地将递归替换为围绕构成过程主体其余部分的两个气泡通道的外部 while 循环(这可能避免了你的大部分困惑......)。

对递归分析有用的算法通常具有某种分而治之的结构,其中递归过程调用解决较小的子问题。您的算法明显缺乏这一点:递归调用的大小始终与原始调用相同。

【讨论】:

  • +1 表示同意该算法对递归毫无价值,因为它没有展示分而治之的技术。它可能应该在数组 A 上递归调用自身,从 Start+1 到 End-1 直到 Start >= End,因为每个调用看起来都保证放置 2 个额外的排序项。如果是这种情况,您可以将递归解决为 F(n) = F(n-2) + 2n 或其他东西
  • 感谢您的回答!我不认为这个算法是为了高效,它只是为了练习。这个算法还有很多问题我没有包括在内,询问算法是否可以改进。
  • 还有一件事,这是否意味着我放在最坏情况列中的所有内容都必须乘以递归调用的数量(即 n/2)?
  • 在你总结之后再乘以可能更有意义。即:计算过程的复杂度减去递归,然后在推理整体性能时将其用作组件。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-28
  • 1970-01-01
  • 1970-01-01
  • 2017-11-20
  • 1970-01-01
相关资源
最近更新 更多