将经典楼梯问题视为“戴维斯的房子里有许多楼梯,他喜欢一次爬上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个值(想象一下递归树)。我认为这是自下而上的。这是正确的吗?
答案 0 :(得分:1)
无论有无记忆力,退缩策略通常都是自上而下的方法。底层算法设计是动态编程,传统上是以自下而上的方式构建的。
我注意到您是用python编写代码的,而python通常对深度回避不满意(少量也可以,但是性能很快受到打击,最大回覆深度为1000-除非自从阅读)。
如果我们创建一个自底向上的动态programmin版本,则可以摆脱这种重复,并且我们还可以认识到我们只需要恒定的空间,因为我们仅对最后三个值感兴趣:>
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开始计数。
答案 1 :(得分: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]