algorithm - 列出所有下楼梯路径的时间复杂度?
问题描述
我无法确定爬楼梯问题的回溯解决方案的时间复杂度
你正在爬楼梯。到达顶部需要 n 步。
每次您可以爬 1 或 2 级台阶。你可以通过多少种不同的方式爬上顶峰?
注意:给定 n 将是一个正整数。
输入:
2
输出:
2
解释:有两种方法可以爬到顶部。
- 1 步 + 1 步
- 2个步骤
我的算法:
input = [1, 2]
output = set()
n = 4
def helper(temp):
if sum(temp) == n:
output.add(tuple(temp))
elif sum(temp) > n:
return
else:
for i in input:
helper(temp + [i])
helper([])
print(output)
n = 4 的输出:
{(1, 2, 1), (2, 1, 1), (1, 1, 2), (2, 2), (1, 1, 1, 1)}
解决方案
这个函数的运行时间是不寻常的 Θ(n · φ n ),其中 φ 是黄金比例,(1 + √5) / 2。
要了解这是为什么,让我们谈谈如何分析您编写的代码。想象一下这段代码的递归树。(这是每个递归调用都有一个节点的树)。请注意,每个递归调用都会分支 - 一次调用大小为 n - 1 的子问题,一次调用大小为 n - 2 的问题。在每个内部节点都在分支的任何树中,总节点数最多为两倍叶数。在您的情况下,找到的每个解决方案都有一个叶子,当递归超过 n 的值时,还有一些额外的叶子。(现在,我们将忽略第二组,但我们稍后会讨论为什么会这样。)这意味着递归调用的总数(前面的警告稍后解决)最多是路径数的两倍下楼梯。
那么这个问题有多少解决方案呢?事实证明,高度为 n 的楼梯的解数正好等于第 n 个斐波那契数,而第 n 个斐波那契数恰好是 Θ(φ n )。所以这意味着总共有 Θ(φ n ) 的总递归调用。
那么这些递归调用需要做多少工作呢?我们可以在 O(n) 上保守地对每个递归调用的工作进行上限,因为在最坏的情况下,将列表加起来 1 + 1 + 1 + ... + 1 n 次。但是我们也可以在 Ω(n) 处将工作量最大的叶子上的功下限,因为在最好的情况下,我们将 2 + 2 + ... + 2 加起来总共 n / 2 次。
总的来说,我们有 Θ(φ n ) 调用,其中底部的调用每个都做 Θ(n) 工作,总共有 Θ(n · φ n ) 工作。
最后一个细节要解决——“超调”并加起来大于 n 的递归调用呢?事实证明,其中也有 O(φ n )。看到这一点的一种方法是,达到 n + 1 的超调方式的数量最多是列出所有大小为 n + 1 的路径的解决方案的数量,其中有 O(φ n )。因此,将这些重新添加并不会改变任何内容。
希望这可以帮助!
推荐阅读
- java - 如何理解 tsp 问题中的这两个软约束?
- python - 我如何知道 linebot URITemplateAction 中选择了哪个选项?
- arrays - Kotlin:十位数
- python - Dockerfile:pip install 失败并显示 requirements.txt(但成功使用单个包)
- python-3.x - 如何在条件位于列表中的情况下使用 np
- flutter - 颤振相机包显示时间码
- javascript - 解构 props 和 state 导致 ESlint 中的未使用状态错误
- mysql-workbench - 如何从工作台中删除例程组错误?
- c# - 发送可分辨 CA 列表作为 TLS 握手服务器 Hello 的一部分
- vpn - shadowsocks 或 l2tp 更快更稳定