用lru_cache提高性能
leetcode 上有一題爬樓梯的題,一個n階的臺階,每次可爬1階或2階,問有多少中爬法。這道題不難,就是一個斐波那契數列。我用循環寫的,沒啥問題。然后看評論里有人用遞歸寫,說會超時。然后有人用了lru_cache裝飾器來提高性能,順利通過。
lru即least recently used,lru_cache可以記錄函數的調用結果,再次使用時直接使用之前的返回值,而不真的再次調用。
注意,被lru_cache裝飾的函數,其參數必須是可哈希的
以上程序輸出為:
可以看到,a(i)實際只執行了5次。lru_cache 的參數maxsize 代表能緩存幾個函數執行的結果。
lru_cache容易讓人聯想到帶備忘的動態規劃,有了lru_cache,豈不是可以直接寫普通的遞歸函數來達到類似動態規劃的效果了?事實是,有時候還是要注意的!
比如,leetcode 第377題“組合總和IV”:
由于“組合總和”前幾題都是用回溯法,這道題我一開始也用回溯法做的:
然而超時了。。。那么就用動態規劃吧。想到lru_cache,我就自頂向下直接遞歸了:
from functools import lru_cacheclass Solution:@lru_cache()def combinationSum(self, candidates, target):if len(candidates)==0:return 0if target == 0:return 1if target < min(candidates):return 0r = 0for x in candidates:r += self.combinationSum(candidates,target-x)return rdef combinationSum4(self, candidates, target):cans = tuple(candidates)return self.combinationSum(cans, target)然而還是超時了。。。在自己電腦上跑了下,提示“RecursionError: maximum recursion depth exceeded in comparison”,原來是超過最大遞歸層數了。。。。查了下最后的測試用例,candidates=[3,33,333],target=10000,確實遞歸層數太深了。所以還是老老實實自己寫了自底向上的動態規劃算法:
class Solution:def combinationSum4(self, candidates, target):men = [0]*(target+1)for i in range(target+1):if i in candidates:men[i] += 1for x in candidates:if i - x >= 0:men[i] += men[i-x]return men[target]總結
以上是生活随笔為你收集整理的用lru_cache提高性能的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: html5文章标题定格,jQuery和c
- 下一篇: 4月18号软件更新资讯合集