fibonacci的4种实现


fibonacci的4种实现.把n=0也考虑在内

工具函数

计算运行时间与内存

def time_memory(func):
    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        tracemalloc.start()
        start = time.perf_counter()
        res = func(*args, **kwargs)
        duration = (time.perf_counter() - start)*1000
        current, peak = tracemalloc.get_traced_memory()
        tracemalloc.stop()
        print(f"{func.__name__} excution duration: {duration:.3f} ms")
        print(f"{func.__name__} memory usage: current = {current / 1024:.3f} KB, peak = {peak / 1024:.3f} KB")
        return res
    return wrapper

1. base递归

最简单的递归实现,此种实现分线下来会有非常多重复子问题计算,导致时间复杂度为O(2^n)指数级别.

def fibonacci_base(n: int):
    if n < 0:
        raise ValueError(f'{n} is invalid')
    elif n == 0:
        return 0
    elif n == 1:
        return 1
    else:
        return fibonacci_base(n-1) + fibonacci_base(n-2)

测试样例

@time_memory
def test_base(n: int):
    res = fibonacci_base(n)
    print(res)

test_base(18)

运行结果

test_base excution duration: 3.812 ms

2. 数组缓存计算结果

考虑到base解法有不少重复计算的数值,可以用一个数组存放已经计算好的数值,递归计算时可以查看数组里面是否有之前已经计算好的值,使用空间换时间的方法,算法时间复杂度O(N) 空间复杂度O(N)

def do_fibonacci_e1(n: int, buffer: list[int]):
    if n < 0:
        raise ValueError(f'{n} is invalid')
    if n == 0:
        return buffer[0]
    elif n == 1:
        if buffer[1] == 0:
            buffer[1] = 1
        return buffer[1]
    else:
        if buffer[n] == 0:
            buffer[n] = do_fibonacci_e1(n-1, buffer) + do_fibonacci_e1(n-2, buffer)
        return buffer[n]

def fibonacci_e1(n: int):
    if n < 0:
        raise ValueError(f'{n} is invalid')
    else:
        buffer = [0] * (n+1)
    return do_fibonacci_e1(n, buffer)

测试样例

@time_memory
def test_e1(n: int):
    res = fibonacci_e1(n)
    print(res)

test_e1(18)

运行结果

test_e1 excution duration: 0.097 m

3. 自底向上迭代替换递归

自底向上的解决办法,使用循环替代递归,时间复杂度O(N) 空间复杂度O(N) 循环实现消耗资源更少,所以时间更快.
代码:

def fibonacci_e2(n: int):
    if n < 0:
        raise ValueError(f'{n} is invalid')
    elif n == 1:
        return 1
    # n >= 2 开始构建数组
    dp = [0]*(n+1)
    dp[0] = 0
    dp[1] = 1
    for i in range(2, n+1):
        dp[i] = dp[i-1] + dp[i-2]
    return dp[n]

测试样例

@time_memory
def test_e2(n: int):
    res = fibonacci_e2(n)
    print(res)

test_e2(18)

运行结果

test_e2 excution duration: 0.052 ms

4. 终极解法,根据状态推导式 f(n) = f(n-1) + f(n-2) 只保留要前两个状态

进一步将时间复杂度降低到O(1)

def fibonacci_e3(n: int):
    if n < 0:
        raise ValueError(f'{n} is invalid')
    elif n == 1:
        return 1
    pre = 0
    curr = 1
    for i in range(2, n+1):
        res = pre + curr
        pre = curr
        curr = res
    return res

测试样例

@time_memory
def test_e3(n: int):
    res = fibonacci_e3(n)
    print(res)

运行结果

test_e3 excution duration: 0.040 ms
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值