【发布时间】:2022-01-09 10:29:31
【问题描述】:
在尝试解决 Leetcode 上的 Combination IV 时,我想出了这个记忆化的解决方案:
def recurse(nums, target, dp):
if dp[target]!=0:
return dp[target]
if target==0:
return dp[0]
for n in nums:
if n<=target:
dp[target] += recurse(nums, target-n, dp)
return dp[target]
class Solution:
def combinationSum4(self, nums: List[int], target: int) -> int:
dp = [0]*(target+1)
dp[0] = 1
return recurse(nums, target, dp)
但这给了我一个超出时间限制的错误。
另一个使用字典而不是 dp 数组来缓存值的记忆化解决方案运行良好并且不超过时间限制。解决方法如下:
class Solution:
def combinationSum4(self, nums: List[int], target: int) -> int:
memo = {}
def dfs(nums, t, memo):
if t in memo:
return memo[t]
if t == 0:
return 1
if t < 0:
return 0
res = 0
for i in nums:
res += dfs(nums, t-i, memo)
memo[t] = res
return res
return (dfs(nums, target, memo))
为什么使用 dict 代替数组可以提高运行时间?这不像我们在遍历数组或 dict,我们只是使用它们来存储和访问值。
编辑:我的代码崩溃的测试用例如下:
nums = [10,20,30,40,50,60,70,80,90,100,110,120,130,140,150,160,170,180,190,200,210,220,230,240,250,260,270,280,290,300,310,320,330,340,350,360,370,380,390,400,410,420,430,440,450,460,470,480,490,500,510,520,530,540,550,560,570,580,590,600,610,620,630,640,650,660,670,680,690,700,710,720,730,740,750,760,770,780,790,800,810,820,830,840,850,860,870,880,890,900,910,920,930,940,950,960,970,980,990,111]
目标 = 999
【问题讨论】:
-
乍一看,我觉得这两个程序之间的区别不仅仅是用数组替换字典。
-
我不这么认为。如果你仔细看,它是一样的。虽然如果您发现任何其他可能有助于程序 2 运行得更快的差异,请告诉我。
-
你能以一种不需要仔细查看的方式来准备代码,但要清楚地表明它们是相同的,除了用数组交换字典吗?
-
一个区别,例如,在上面的代码中,
dp[target] +=发生在循环内部,而在下面的代码中,memo[t] =在循环之外发生。 -
其中一个测试用例可能有一个巨大的目标值,这将使基于 dict 的代码更快。
标签: python python-3.x memoization