如何解决斐波那契中缺少函数调用使用动态编程记忆
我写了2个fibonacci函数,一个是使用递归,果然fibonacci_recursive(4)在调用栈中有9个函数调用:
def fibonacci_recursive_1(n):
if n == 0 or n == 1: # base case
result = n
print('return from base case,n = ',n,',fib({}) = '.format(n),result)
return result
else: # recursive case
result = fibonacci_recursive_1(n-2) + fibonacci_recursive_1(n-1)
print('return from recursive case,result)
return result
fibonacci_recursive_1(4)
从基本情况返回,n = 0,fib(0) = 0
从基本情况返回,n = 1,fib(1) = 1
递归情况返回,n = 2,fib(2) = 1
从基本情况返回,n = 1,fib(1) = 1
从基本情况返回,n = 0,fib(0) = 0
从基本情况返回,n = 1,fib(1) = 1
递归情况返回,n = 2,fib(2) = 1
递归情况返回,n = 3,fib(3) = 2
递归情况返回,n = 4,fib(4) = 3
3
然后我用动态编程记忆做了一个
stored_results = {}
def fibonacci_dynamic_1(n):
result = 0
if n in stored_results: # memoization
result += stored_results[n]
print('return from cached results,result)
return result
else:
if n == 0 or n == 1: # base case
result = n
stored_results[n] = result
print('return from base case,result)
return result
else: # recursive case
result = fibonacci_dynamic_1(n-2) + fibonacci_dynamic_1(n-1)
stored_results[n] = result
print('return from recursive case,result)
return result
fibonacci_dynamic_1(4)
令我惊讶的是,fibonacci_dynamic(4) 的调用堆栈中只剩下 7 个函数调用了:
从基本情况返回,n = 0,fib(0) = 0
从基本情况返回,n = 1,fib(1) = 1
递归情况返回,n = 2,fib(2) = 1
从缓存结果返回,n = 1,fib(1) = 1
从缓存结果返回,n = 2,fib(2) = 1
递归情况返回,n = 3,fib(3) = 2
递归情况返回,n = 4,fib(4) = 3
3
我明白,如果我使用字典来存储以前计算的结果,它会加快计算速度并且不会重复计算。
但是对于动态编程,难道不应该有相同的 9 个函数调用,其中一些将被替换为“从缓存结果返回”(因为它们是计算过的),而不是仅仅显示只剩下 7 个函数调用?
有什么遗漏或我没有正确编码吗?
解决方法
请注意,动态规划方法可以防止递归的指数爆炸。
在递归方法中,要计算 fib(4),您首先需要计算 fib(3) 和 fib(2)。
要计算 fib(3),您需要计算 fib(2) 和 fib(1)
现在在这个列表中,我们已经计算了 fib(2) 两次。
要计算 fib(2),我们需要 fib(1) 和 fib(0)。
所以最后,我们进行的调用是: 纤维蛋白(4) fib(3) fib(2) fib(2) fib(1) fib(1) fib(0) fib(1) fib(0)
总共 9 个电话。
在动态方法中,要计算 fib(4),您需要计算 fib(3) 和 fib(2)。一旦我们计算了 fib(3),我们就不需要再次计算 fib(2),因为它已经在 fib(3) 期间计算过了。所以我们有:
您的调用优先考虑深度,因此调用方式如下:
fib(4) -> fib(3) -> fib(2) -> fib(1):基本情况,-> fib(0):基本情况
然后我们向上移动堆栈:fib(3) 也调用 fib(1) 但从基本情况返回。 然后 fib(4) 也调用 fib(2) 但从查找中返回。
总共有 7 个调用。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。