这个递归函数的运行时间是多少?
Posted
技术标签:
【中文标题】这个递归函数的运行时间是多少?【英文标题】:What is the running time of this recursive function? 【发布时间】:2016-03-06 18:23:36 【问题描述】:我很难弄清楚这个简单递归函数的运行时间。
void myRecur(int n)
if (n < 1) return;
cout << n << " ";
myRecur(n/2);
cout << n << " ";
myRecur(n/2);
我认为它会打印:4 2 1 1 2 1 1 4 2 1 1 2 1 1 for myRecur(4)。
另外,这个函数在时间复杂度方面是否类似于树遍历函数?
非常感谢任何有关理解递归的建议和对此特定问题的运行时间的详细解释。
【问题讨论】:
一旦你知道它打印了什么,你就知道运行时间了,对吧?那么它打印什么? 我认为它会打印: 4 2 1 1 2 1 1 4 2 1 1 2 1 1 - 显然这是初始n
为 8 时,所以你知道myRecur(8)
调用了这个函数 15 次,或者2n-1
次。如果您将初始输入更改为 16、32、64、128,模式是否变得明显(或者,检查代码本身,您能否预测是否会出现这种模式)?如果是这样,您已经找到了答案。至于类似于树遍历 - 如果它是人们指望效率的树遍历,则不是!
@mah 感谢您的意见。你是对的,我可以增加输入的大小并根据结果猜测运行时间。但是,我正在寻找一种通用的方法来分析函数,即使用递归关系或递归树来查找运行时间。
@root 不同的递归函数有不同的标准,它们将如何根据提供的输入进行递归。由于这些标准不是通用的,因此您的解决方案也不是通用的。
【参考方案1】:
这是使用递归关系的好地方!让我们让 T(n) 是算法在大小为 n 的输入上运行所花费的时间。那么
T(0) = 1,因为基本情况做的工作量是恒定的,并且 T(n) = 2T(⌊n/2⌋) + 1,因为每个其他情况都会对大小为 n/2 的问题进行两次递归调用,并执行额外的恒定工作量。现在的目标是找到某种以非递归方式描述 T(n) 的表达式。有很多方法可以做到这一点。查找迭代方法和递归树方法以获取一些示例。最快的方法是使用名副其实的主定理,它可以让你直接从递归关系中确定时间复杂度。在这种情况下,主定理说这解决了 T(n) = Θ(n)。
【讨论】:
非常感谢!只是一个后续,对于基本情况,为什么它是 T(1) = 1?我认为它是 T(0) = 1,因为基本情况发生在 ncout << n
是 O(log n),而不是 O(1)。
@PaulHankin 这是一个很好的观点——我以前从未想过这一点!【参考方案2】:
我认为您对最坏情况感兴趣,因此代码复杂度为 Ο(n)。对于给定的 n,您的函数最多会运行 2n-1 次。
为了更好地理解,尝试构建一个调用树。
n
n/2 n/2
n/4 n/4 n/4 n/4
...
有 ⌊log2(n)⌋ 个级别。每个级别都有 2lvl 项。项目总数为 2n - 1。
【讨论】:
以上是关于这个递归函数的运行时间是多少?的主要内容,如果未能解决你的问题,请参考以下文章