0

将经典楼梯问题考虑为“戴维斯在他的房子里有许多楼梯,他喜欢一次爬每一个楼梯 1、2 或 3 级。作为一个非常早熟的孩子,他想知道有多少种方法可以到达楼梯顶。”

我的方法是使用带有递归的记忆作为

# TimeO(N), SpaceO(N), DP Bottom Up + Memoization
def stepPerms(n, memo = {}):

    if n < 3:
        return n
    elif n == 3:
        return 4

    if n in memo:
        return memo[n]
    else:
        memo[n] = stepPerms(n - 1, memo) + stepPerms(n - 2 ,memo) + stepPerms(n - 3 ,memo)
        return memo[n]

我想到的问题是,这个解决方案是自下而上还是自上而下。我的处理方法是,因为我们一直向下计算上 N 个值(想象一下递归树)。我认为这是自下而上的。这个对吗?

4

2 回答 2

2

递归策略通常是自上而下的方法,无论它们是否有记忆。底层算法设计是动态规划,传统上以自下而上的方式构建。

我注意到你用 python 编写了你的​​代码,而 python 通常对深度递归不满意(少量还可以,但性能很快就会受到影响,并且最大 recousion 深度为 1000 - 除非在我读到它之后它被改变了) .

如果我们制作一个自下而上的动态程序版本,我们可以摆脱这种重复,我们也可以认识到我们只需要恒定数量的空间,因为我们只对最后 3 个值真正感兴趣:

def stepPerms(n):
    if n < 1: return n
    memo = [1,2,4]
    if n <= 3: return memo[n-1]

    for i in range(3,n):
        memo[i % 3] = sum(memo)
    return memo[n-1]

请注意逻辑是多么简单,从 i 开始的 appart 比值小 1,因为位置从 0 开始,而不是从 1 开始。

于 2019-06-23T15:21:15.357 回答
0

在自顶向下的方法中,复杂的模块被划分为子模块。所以这是自上而下的方法。另一方面,自下而上的方法从基本模块开始,然后将它们进一步组合。

该解决方案的自下而上方法将是:

memo{}

for i in range(0,3):
   memo[i]=i
memo[3]=4

for i in range(4,n+1):
  memo[i]=memo[i-1]+memo[i-2]+memo[i-3]
于 2019-06-23T15:03:49.553 回答