python3记忆化搜索@lru_cache(None)实践

本文介绍了如何利用lru_cache实现记忆化递归,以避免在‘canCross’函数中对同一状态的多次计算,特别是在dfs函数中。通过lru_cache机制,当输入参数相同时,函数会直接返回缓存的结果,显著提高了算法效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

存在对同一状态多次求值,所以用记忆化递归,dfs前面加上@lru_cache(None)当参数相同时直接返回值不需要重复计算。

lru_cache全称是Least Recently Used Cache,即最近最少使用缓存。

from functools import lru_cache

def canCross(stones: List[int]) -> bool:
    @lru_cache(None)
    def dfs(pos,step):
        if pos==stones[-1]: return True
        for d in [-1,0,1]:
            if step+d>0 and pos+step+d in set(stones):
                if dfs(pos+step+d, step+d):
                    return True
        return False
    pos, step = 0, 0
    return dfs(pos, step)
<think>嗯,用户想了解如何使用Python的functools.lru_cache装饰器。首先,我需要回忆一下lru_cache的基本功能和用法。记得这个装饰器是用来缓存函数调用结果的,特别是对于那些计算量大的函数,可以避免重复计算,提高性能。根据引用[4],它是基于最近最少使用策略的缓存,当缓存满了之后会自动移除最久未使用的项。 然后,用户可能想知道如何正确使用它。基本用法应该是在函数定义前加上@lru_cache装饰器。不过要注意函数的参数必须是可哈希的,比如不可变类型,像整数、字符串、元组等。如果参数里有不可哈希的类型,比如列表,就会报错,如引用[3]中的例子,因为列表是不可哈希的,所以需要将参数改为元组或者其它可哈希类型。 接下来,可能需要解释如何设置缓存的大小。maxsize参数用来指定缓存的最大容量,如果设为None的话,缓存可以无限制增长,不过可能会消耗较多内存。另外,typed参数如果设置为True,会区分参数的类型,比如33.0会被当作不同的参数处理。 用户可能还会遇到缓存失效的问题,所以需要说明如何手动清除缓存,比如使用cache_clear()方法。或者需要动态调整maxsize的话,可以重新装饰函数。 然后,应该举几个例子,比如斐波那契数列的递归优化,用lru_cache来缓存中间结果,避免重复计算。代码示例需要正确展示装饰器的使用,并说明加上之后性能的提升,如引用[1]和[2]提到的。 还要提醒用户常见的错误,比如参数不可哈希的情况,以及如何解决。例如,将列表参数转换为元组,或者在函数内部处理可变参数。 最后,生成相关问题,帮助用户进一步学习,比如如何调整缓存大小,处理不可哈希参数,性能优化的实际案例,以及与其他缓存装饰器的比较。 现在需要把这些点整理成一个结构清晰的回答,确保每个部分都有对应的引用标注,并且代码示例正确,符合LaTeX格式要求。同时,要使用中文,保持自然流畅,避免使用Markdown格式,行内公式用$包裹,独立公式用$$。还要检查是否有遗漏的注意事项,比如typed参数的用法,或者缓存的线程安全等问题,但根据现有引用,可能不需要深入线程问题,保持基础即可。</think>### Python functools.lru_cache 装饰器使用详解 #### 1. 基本概念 `functools.lru_cache` 是 Python 标准库提供的装饰器,用于缓存函数计算结果,特别适用于**重复调用且计算成本高**的函数[^4]。其核心机制是最近最少使用(LRU)策略,当缓存达到指定大小时,自动淘汰最久未使用的缓存项。 #### 2. 基础用法 ```python from functools import lru_cache @lru_cache(maxsize=128, typed=False) def calculate(a: int, b: float) -> float: print("执行计算...") # 仅第一次调用时打印 return a * b + (a - b) ``` - **`maxsize`**: 缓存容量,默认 128。设为 `None` 表示无限制(可能内存耗尽)。 - **`typed`**: 若为 `True`,则区分参数类型(如 `3` 和 `3.0` 视为不同参数)。 #### 3. 典型场景:优化递归函数 以斐波那契数列为例,未使用缓存时时间复杂度为 $O(2^n)$,使用后降为 $O(n)$: ```python @lru_cache(maxsize=None) def fibonacci(n): if n < 2: return n return fibonacci(n-1) + fibonacci(n-2) ``` #### 4. 注意事项 - **参数必须可哈希**:若参数含列表等不可哈希类型,需转换为元组(如 `tuple(nums)`)或调整设计[^3]。 - **缓存手动清除**:通过 `fibonacci.cache_clear()` 清空缓存。 - **线程安全**:在并发场景下需自行加锁。 #### 5. 错误处理示例 ```python # 错误用法:参数含列表 @lru_cache def sum_list(nums): return sum(nums) sum_list([1, 2, 3]) # 报错:TypeError: unhashable type: &#39;list&#39; # 正确改进:将列表转为元组 @lru_cache def sum_list_tuple(nums_tuple): return sum(nums_tuple) sum_list_tuple(tuple([1, 2, 3])) # 正常执行 ``` #### 6. 性能对比 引用测试案例:使用 `lru_cache` 后,某递归函数运行时间从 12.3 秒缩短至 0.4 秒[^1]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

YMWM_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值