Performance (Lisp)我能让这更有效吗?
我用lisp编写了这个递归函数,我想知道是否有人有什么技巧可以让它更有效?如果数字太大,它只是开始破裂,需要大约3分钟来计算不同组合的10英镑等值! 即使给我指出正确的方向也很好,谢谢Performance (Lisp)我能让这更有效吗?,performance,recursion,lisp,common-lisp,Performance,Recursion,Lisp,Common Lisp,我用lisp编写了这个递归函数,我想知道是否有人有什么技巧可以让它更有效?如果数字太大,它只是开始破裂,需要大约3分钟来计算不同组合的10英镑等值! 即使给我指出正确的方向也很好,谢谢 (defun dollars (amount &optional (coins '(5 10 20 50 100 200 500 1000 2000 5000 10000))) (cond ((= amount 0) 1) ((or (< amount 0) (= (length
(defun dollars (amount &optional (coins '(5 10 20 50 100 200 500 1000 2000 5000 10000)))
(cond ((= amount 0) 1)
((or (< amount 0) (= (length coins) 0) (> amount 30000)) 0)
((zerop (mod amount 5))
(+ (dollars (- amount (first coins)) coins)
(dollars amount (rest coins))))))
(除美元(金额和可选(硬币)(51020501002000500010000)))
(条件(=金额0)1)
((或(<金额0)(=(长度硬币)0)(>金额30000))0)
((零利率(调整金额5))
(+(美元(-amount(第一枚硬币))硬币)
(美元金额(剩余硬币(()())))
让我们看一个类似的问题,计算斐波那契数
(defun fib (n)
(if (<= 0 n 1)
n
(+ (fib (- n 1))
(fib (- n 2)))))
(定义fib(n)
(如果(一个非常简单的加速:用(endp coins)
替换(=(length coins)0)
。必须遍历整个列表来计算其长度,而它可以很快判断列表是否为空。那太好了!我没有意识到这会有很大的区别:)另一个简单的加速方法是:颠倒硬币列表!当金额小于下一个更高的硬币时,你可以为每一个剩余硬币节省两次通话费。你也可以通过将(
替换为(
。非常感谢!我在互联网上搜索这类东西已经很久了,但很难理解,因为这很有道理!嗨,我尝试过实现它,但不管我怎么做,它都会返回错误的结果,使数字比它应该的大很多?@Rebeccawide你确定这些值不正确吗不正确?它们确实呈指数增长,所以你应该期望它们真的很大。@Rebeccawide你在记忆中同时使用数量和硬币吗?否则,例如(10美元)(5美元10))
(10美元(5))
将导致结果错误。使用(使哈希表:test#“相等”)
和(gethash(cons-amount-coins)*结果*)
将给出与无需记忆相同的结果。
(defparameter *calculated* (make-hash-table))
(defun fib (n)
(or (gethash n *calculated*)
(setf (gethash n *calculated*)
(if (<= 0 n 1)
n
(+ (fib (- n 1))
(fib (- n 2)))))))