我正在研究一种算法来计算构建100美分的方法,给出无限量的硬币,硬币,零钱和四分之一。
我最终选择了以上(AFAIK的工作原理):
def count_ways(amount)
num_ways(amount, 0)
end
def num_ways(amount, index)
return 1 if amount == 0
return 0 if index >= COINS.length || amount < 0
num_ways(amount - COINS[index], index) +
num_ways(amount, index + 1)
end
现在,我想记住这个算法。我发现考虑记忆的一种有效方法是考虑我们反复传递给这个函数的输入。在这种情况下,我想记住金额和金额的组合。索引参数。
通常当我有两个参数时,我会构建一个两个D数组作为记忆的方法,但这里的意义却大打折扣。那么,你怎么能记下这两个参数呢?做这样的事情有意义吗?
def count_ways(amount)
memo = Hash.new { |h, k| h[k] = [] }
num_ways(amount, 0, memo)
end
def num_ways(amount, index, memo)
return 1 if amount == 0
return 0 if index >= COINS.length || amount < 0
memo[amount - COINS[index], index] ||= num_ways(amount - COINS[index], index)
memo[amount, index + 1] ||= num_ways(amount, index + 1)
memo[amount - COINS[index], index] +
memo[amount, index + 1]
end
答案 0 :(得分:0)
我相信在解决算法任务时没有通用的方法来实现memoization。因为速度快。您必须选择的方式取决于您的算法,输入数据等。 几个必要的规则:
h = {}; h[ [1,2] ]
= 3
只会为密钥生成COINS.size
* amount
Array
Array
用于连续的数据,将Hash
用于有缺口的一个Hash
代替Array
Array
连续数据大小使用该规则,memoization(仅在您的情况下,COINS.size
&lt;&lt; amount
并且两个数据连续)可能如下所示:
COINS = [25, 10, 5, 1]
def count_ways(amount)
# memo is just COINS.size + 1 Array instances
# a[0] = 1 instead of return 1 if amount == 0
memo = Array.new(COINS.size){ Array.new(amount).tap{ |a| a[0] = 1 } }
num_ways(amount, 0, memo)
end
def num_ways(amount, index, memo)
return 0 if index >= COINS.size || amount < 0
memo[index][amount] ||=
num_ways(amount - COINS[index], index, memo) +
num_ways(amount, index + 1, memo)
end
P.S。 dynamic-programming
标记是不必要的:)
答案 1 :(得分:-1)
由于相同的数组具有不同的对象ID,因此您无法将值作为数组放入散列键中。但是你可以转换为字符串来制作一个简单的查找结构,例如转换为YAML / JSON
require 'json'
memo = {}
def memoize(*args, &blk)
memo[args.to_json] ||= blk.call
end
def num_ways(amount, index)
memoize(amount, index) do
# original method body
end
end
修改的
没关系,我想我需要使用to_json
。您可以在args
内使用memoize
而不是args.to_json
。