【问题标题】:Big-O notation for two simple recursive functions两个简单递归函数的大 O 表示法
【发布时间】:2013-04-20 00:06:02
【问题描述】:

我在 Python 中有两个递归函数,只是想知道它们的大 O 表示法。这些的大 O 是什么?

def cost(n):
    if n == 0:
        return 1
    else:
        return cost(n-1) + cost(n-1)

def cost(n):
    if n == 0:
        return 1
    else:
        return 2*cost(n-1)

【问题讨论】:

  • 我认为第一个是O(2^n),第二个是O(n)
  • 如果您解释一下您是如何得出这些 O 的,我会赞成将其作为答案。
  • 同样,罗伯特·哈维。

标签: python algorithm math recursion big-o


【解决方案1】:

让我们使用递归关系来解决这个问题!第一个函数的运行时可以递归描述为

T(0) = 1

T(n + 1) = 2T(n) + 1

也就是说,基本情况需要一个时间单位才能完成,否则我们会对问题的较小实例进行两次递归调用,并进行一些设置和清理工作。展开这个循环中的一些术语,我们得到

  • T(0) = 1
  • T(1) = 2T(0) + 1 = 2 + 1 = 3
  • T(2) = 2T(1) + 1 = 2 × 3 + 1 = 7
  • T(3) = 2T(2) + 1 = 2 × 7 + 1 = 15

这个系列 1, 3, 7, 15, ... 可能看起来很眼熟,因为它是 21 - 1, 22 - 1, 2 3 - 1 等。更一般地,我们可以证明

T(n) = 2n+1 - 1

我们可以通过归纳来做到这一点。作为我们的基本情况,T(0) = 1 = 21 - 1,因此对于 n = 0,该声明成立。现在假设对于某些 n,T(n) = 2n +1 - 1. 然后我们就有了

T(n + 1) = 2T(n) + 1 = 2(2n+1 - 1) + 1 = 2n+2 - 2 + 1 = 2n+2 - 1

我们完成了!由于这个循环的结果是 2n+1 - 1 = 2(2n) - 1,我们有运行时间是 Θ(2n支持>)。

第二个函数的运行时间可以递归描述为

T(0) = 1

T(n + 1) = T(n) + 1

扩展一些术语:

  • T(0) = 1
  • T(1) = T(0) + 1 = 1 + 1 = 2
  • T(2) = T(1) + 1 = 2 + 1 = 3
  • T(3) = T(2) + 1 = 3 + 1 = 4

这给出了 1, 2, 3, 4, ...,所以更一般地说我们可能会猜到

T(n) = n + 1

我们可以再次归纳证明这一点。作为基本情况,如果 n = 0,则 T(0) = 1 = 0 + 1。对于归纳步​​骤,假设对于某些 n,T(n) = n + 1。然后

T(n + 1) = T(n) + 1 = n + 1 + 1 = n + 2

我们完成了!由于运行时间是 n + 1,所以运行时间是 Θ(n)。

希望这会有所帮助!

【讨论】:

  • 如果你愿意,添加一个关于 memoization 的注释似乎很合适,它可以将指数运行时间减少到线性
  • 这是一个史诗般的答案。它有很大帮助。在分析空间方面,你有什么办法可以指出我类似的东西吗?
  • 好方法!但是,直到我阅读另一个解释您所描述的相同重复关系的站点之前,我并没有完全理解这种方法。 cs.duke.edu/~ola/ap/recurrence.html 只是把链接放在这里,以防它帮助任何人。
【解决方案2】:

使用递归树(通过可视化图表)查找成本。

函数cost(n)的递归关系

                    T(n) = 2T(n-1)+c

If at kth level input size become 0 (base condition where func terminates)
                                           n-k =0
                                              k=n


Total cost of the function (adding cost of each level) :
             T(n) = 2^0*c+ 2^1*c + 2^2*c + 2^3*c +.. .. . .+ 2^n * c
                  = O(2^n)

类似的方法我们可以找到第二个函数的时间复杂度。

【讨论】: