You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何计算斐波那契数时记忆化(memoization)耗时近乎恒定,与动态规划差异显著?

为什么记忆化斐波那契实现耗时近乎恒定,与动态规划表现截然不同?

先看我们实现的两种斐波那契数计算代码:

def fibo_memo(i, memo={}):
    if i <= 0:
        return 0
    elif i == 1:
        return 1
    elif i in memo:
        return memo[i]
    else:
        memo[i] = fibo_memo(i-2, memo) + fibo_memo(i-1, memo)
        return memo[i]

def fibo_dp(i):
    if i <= 0:
        return 0
    elif i == 1:
        return 1

    dp = [0] * (i + 1)
    dp[1] = 1

    for j in range(2, i + 1):
        dp[j] = dp[j-1] + dp[j-2]

    return dp[i]

assert(fibo_memo(100) == fibo_dp(100))

对应的性能测试结果:

i = 10
%timeit fibo_memo(i)  # 73 ns
%timeit fibo_dp(i)  # 309 ns

i = 100
%timeit fibo_memo(i)  # 73 ns
%timeit fibo_dp(i)  # 2.54 微秒

i = 1000
%timeit fibo_memo(i)  # 73 ns
%timeit fibo_dp(i)  # 33 微秒

核心差异分析

  • 记忆化版本的持久缓存特性:
    fibo_memo的memo参数用了默认空字典,而Python里函数的默认参数是在函数定义时就创建的,并非每次调用都重建。第一次调用时,递归计算出的所有斐波那契值都会存入这个全局唯一的memo字典;之后无论传入多大的i,只要该值已存在于memo中,就直接返回缓存结果——这是O(1)的字典查找操作,所以耗时几乎恒定。

    哪怕先调用fibo_memo(1000)再调用fibo_memo(10),耗时也不会有明显变化,因为所有值都已经提前缓存完毕。

  • 动态规划版本的全量重计算逻辑:
    fibo_dp每次调用都会从头执行完整流程:创建长度为i+1的数组,再从j=2循环到j=i逐个计算值。这个过程的时间复杂度是O(n),i越大,数组长度越长、循环次数越多,耗时自然线性增长,和测试结果完全匹配。

额外验证点

如果想让记忆化版本的耗时随i变化,可以每次调用手动传入空字典(比如fibo_memo(100, {})),这时它会重新递归计算所有值,耗时就会和i正相关。

内容的提问来源于stack exchange,提问作者THN

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 06:37:17