函数范式中的动态规划
2022-09-02 00:16:34
我正在研究欧拉计划的第三十一个问题,它询问,使用任意数量的1p,2p,5p,10p,20p,50p,£1(100p)和£2(200p)的硬币赚取£2的不同方法。
有递归解决方案,例如Scala中的这个解决方案(归功于Pavel Fatin)
def f(ms: List[Int], n: Int): Int = ms match {
case h :: t =>
if (h > n) 0 else if (n == h) 1 else f(ms, n - h) + f(t, n)
case _ => 0
}
val r = f(List(1, 2, 5, 10, 20, 50, 100, 200), 200)
尽管它运行得足够快,但效率相对较低,调用该函数大约560万次。f
我看到其他人在Java中的解决方案是动态编程的(归功于来自葡萄牙的wizeman)
final static int TOTAL = 200;
public static void main(String[] args) {
int[] coins = {1, 2, 5, 10, 20, 50, 100, 200};
int[] ways = new int[TOTAL + 1];
ways[0] = 1;
for (int coin : coins) {
for (int j = coin; j <= TOTAL; j++) {
ways[j] += ways[j - coin];
}
}
System.out.println("Result: " + ways[TOTAL]);
}
这效率更高,并且仅通过内部循环1220次。
虽然我显然可以使用对象或多或少地将其逐字翻译成Scala,但是否有一种惯用的函数式方法可以使用不可变的数据结构来做到这一点,最好具有类似的简洁性和性能?Array
我已经尝试过,但陷入了试图递归更新之前,我决定我可能只是以错误的方式接近它。List