【问题标题】:Time Complexity of a recursive function where the base case isn't O(1)基本情况不是 O(1) 的递归函数的时间复杂度
【发布时间】:2020-10-25 16:55:50
【问题描述】:

我见过的大多数递归函数(例如 Fibonacci 或 Hanoi)都有 O(1) returns,但如果不是 O(1) 而是 O(n)

例如,具有 O(n) 基本情况的递归斐波那契:

class fibonacci { 
    static int fib(int n) { 
      if (n <= 1) 
        for (int i=0;i<n;i++) {
          // something
        }
      return n;
    return fib(n-1) + fib(n-2); 
    } 
       
    public static void main (String args[]) 
    { 
    int n = 9; 
    System.out.println(fib(n)); 
    } 
} 

【问题讨论】:

  • 您必须计算基本情况由fib(n) 触发的次数;将此计数乘以基本情况的复杂性;并将其添加到您的复杂性计算中。斐波那契的这段代码已经非常复杂了。添加n * (number of calls to fib(0) and fib(1)) 只会让情况变得更糟。
  • 我从中截取这个的网站说斐波那契复杂度(没有 for 循环)是 O(2^n),这个复杂度是多少? O(2^n+n*2^n)?
  • 是的。请注意,O(2^n) 是斐波那契简单实现的粗略上限。它实际上是 Θ(φ^n) ≈ Θ(1.618^n)。如果两个递归调用是对fib(n-1),则为Θ(2^n),但其中一个是对fib(n-2),这使它稍微快一些。

标签: performance recursion time-complexity fibonacci


【解决方案1】:

您在此处编写的函数的基本情况实际上仍然具有时间复杂度O(1)。原因是如果base case在这里触发,那么n≤1,所以这里的for循环最多会运行一次。

因为当输入大小较小时会触发很多基本案例,所以当算法的输入大小为 O(n) 时,相对而言很少会获得运行时间为 O(n) 的基本案例em>n。这意味着基本情况与数组大小无关,这可能会发生,但有些不寻常。

一个更常见的情况 - 尽管我认为仍然很不常见 - 是递归函数有两个不同的参数(例如,nk ),其中递归减少了 n 但保持 k 不变。例如,假设您使用此处的代码并将基本情况下 n 上的for 循环替换为基本情况下 k 上的for 循环。然后会发生什么?

这是一个有趣的问题。在这个特定问题的情况下,这意味着完成的总工作将由 O(k) 乘以触发的基本案例数加上 O(1)乘以非基本情况递归调用的次数。对于斐波那契递归,触发计算 Fn 的基本情况数为 Fn+1 并且有 (Fn+1 - 1 ) 非基本情况调用,因此整体运行时间为 Θ(k Fn+1 + Fn+1) = Θ(k φn )。对于河内塔,您同样会看到整体运行时间为 Θ(k 2n) 的缩放效果。但是对于其他递归函数,运行时可能会以不同的方式发生变化,具体取决于这些函数的结构。

希望这会有所帮助!

【讨论】:

    猜你喜欢
    • 2017-12-31
    • 2020-07-14
    • 1970-01-01
    • 2018-05-29
    • 2018-08-18
    相关资源
    最近更新 更多