Performance (Lisp)我能让这更有效吗?

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

我用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 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)))))))